BAJA OpCode suggestion
From
Angus Netfoot@VERT/TALAMASC to
Digital Man on Thu Dec 16 11:56:00 1999
RE: BAJA OpCode suggestionãBY: Digital Man to Angus Netfoot on Thu Dec 16 1999 01:00 pmãã > > I'd like to suggest the introduction of a new BAJA opcode. I don't knowã > > you would call it, but in effect it would allow run-time modification ofã > > BAJA code-space in a way similar to the POKE opcode known to BASIC prograã >ã > Do you have a suggested syntax? Classic poke functions take an address andã > value, but how would the programmer know what address to poke? Perhaps anã > offset from the start of the current module's image? An absolute address woã > probably be pretty useless.ããI've been thinking about it some more.ããThe idea is to allow the programmer to generate code on-the-fly for immediateãexecution without the overhead of writing a .BIN file to disk and thenãexecuting it. I figure that means either a POKE of some sort allowing theãcode space to be changed, or an EXEC_STR that allows a sequence of BAJA/SBBSãinstructions in string to be executed. I'm not sure which one is the mostãsuitable there are probably good reasons for and against both.ããIf we could do this, we could look at BAJA operation codes as low-levelãbuilding blocks, and construct higher-level operations out of them. Theseãhigher-level operations would only need to be known to the BAJA compiler,ãwhich would translate any high-level concept into the lower-level codes thatãSBBS can understand and interpret.ããIf you are going to POKE stuff into the current code-space you probably needãto say WHAT to poke, WHERE to poke it, and HOW MUCH of it to poke. You mightãwant to poke the least significant 1, 2 or 4 bytes of an integer (or integerãconstant?) or maybe the first 18 bytes of a string (string constant?). Youãwould want to poke relative to your own position, or absolute to the code-ãspace (POKER / POKEA maybe? or with a flag?). So maybe something like:ãã POKE <location> <value> <size> <flags>ãã<flags> might select RELATIVE or ABSOLUTE location, or even something weirdãlike RELATIVE_TO_ABSOLUTE_LABEL so you could POKE at Label+2 or something.ãYou might introduce a Pseudo-Label meaning "Here" so you could poke to $+6ãor whatever. ããWith <size> defaulted to 4 and <flags> defaulted to maybe RELATIVE then theãlast two would disappear in a lot of cases and the last one in almost allãcases, so the normal usage would be:ãã POKE <location> <value>ããAs an alternative to the POKE idea, there is EXEC_STR as in something like:ãã EXEC_STR <string to execute> <start offset> <flags>ããThe <flags> parameter could allow you to select whether to execute in theãcurrent scope or it's own local scopeperhaps? And default to the currentãscope. The <start offset> would default to zero mostly, I suppose, but wouldãallow you to jump into the code-string somewhere in the middle.ããThis looks like it could be good. EXEC_STR would allow you to constructãessentially mini-routines of a few dozen instructions in a string, withoutãworrying about where each part of each instructions was to be poked to. Butãthere are probably lots of worrysome complications. Recursive EXEC_STRãoperations embedded in a string that you are already EXEC_STR-ing?ãPerforming loops and other branch-type operations within the string beingãEXEC_STR-ed? Needs thought.ãã > Might as well through a peek function in there too, eh? :-)ããCouldn't hurt, although no immediate use comes to mind... Are you thinking ofãanything specific?ãã > To make it even more useful, pre-allocated data blocks (in the module codeã > space, so they could be peeked/poked) would be nice.ããI'm not sure I get what you are aiming at.ãã > Probably could use a WORD and DWORD variant of peek/poke too.ããI think that you _do_ need to allow for variable length POKE operations, likeãpoking a single or two-byte op-code or a 4-byte operand CRC32 "address". Iãrather like the idea of being able to poke arbitrary strings of bytes so thatãyou could construct a sequence of instructions using a single SPRINTF orãsomething (or even read a string from disk), POKE the entire thing in one go,ãand then CALL it, GOTO it, or fall through into it.ããHmmm. Some other instructions might be useful to support this, like a way toãdeclare a block of space with a label on it maybe? Oh, this is what you meantãearlier by pre-allocated data blocks. Yes. Good plan.ãã #Hello World the HARD wayã SPRINTF Some_Str "\x51Hello, World!" # x51 = PRINTã POKE PokeHere Some_Str 13ã :PokeHereã DEF_BYTES 13ããsort of thing.ãã > That could really open up possiblities to the enterprising programmer.ããActually, it's sorta scary! :) Suppose we had the POKE op-code and we agreedãon a notational equivilence for array syntax. Example, suppose we agreed thatãã ADD MyArray[Dest] YourArray[Source]ããis only a notational shorthand forãã ADD MyArray.32 YourArray.Wednesdayããassuming that Dest = 32 and Source = "Wednesday". Then we could do somethingãlike:ãã INT SAddr # we need theseã STR IAddr1 IAddr2ãã SPRINTF SAddr "MyArray.%ld" Dest # compute CRC\Address of Destã STRUPR SAddrã CRC32 Iaddr1 Saddrãã SPRINTF SAddr "YourArray.%s" Source # compute CRC\Address of Sourceã STRUPR SAddrã CRC32 IAddr2 Saddrãã POKE Modify+2 IAddr1 # Modify code-space Destã POKE Modify+6 IAddr2 # Modify code-space Sourceãã :Modifyã ADD Dummy Dummy # This is modified by the POKEããWe have just added two array elements together, computing the elements at run-ãtime and we have used numeric and non-numeric indexes to boot. And the onlyãnew instruction introduced is the POKE itself.ããOr instead of poke, you could doãã SPRINTF CodeStr "\x7F\x38%ld%ld" IAddr1 IAddr2 # neat!ã EXEC_STR CodeStrããThe coding looks awful, but it could be simplified by a few new supportãoperations. Maybe something similar to an SPRINTF that combined it'sãarguments in some standard way, did a strupr() on the entire thing andãcomputed the CRC all in one operation. But this is only icing, becauseãyou could simply change BAJA.EXE to readãã ADD MyArray[Dest] YourArray[Source]ããand generate the necessary long-hand code invisibly, "behind the scenes" asãit were. Or you could leave the BAJA compiler alone and let programmersãdevelop their own pre-processor.ããTo declare an array,ãã INT Array[10..16] Yours[RED, GREEN, BLUE] X[1..3][A, B, C]ããcould be a notational convenience meaningãã INT Array.10 Array.11 Array.12 Array.13 Array.14 Array.15 Array.16ã INT Yours.RED Yours.GREEN Yours.BLUEã INT X.1.A X.1.B X.1.C X.2.A X.2.B X.2.C X.3.A X.3.B X.3.CããAnd either left to the programmer to hand-translate or handled by some sort ofãpreprocessor or by BAJA.EXE itself.ããYou could do multiple indexes (multi-dimensional arrays) by a similar processãwhere the "address" of the element could be computed by:ãã SPRINTF SAddr "Array.%ld.%ld.%ld" X Y Z # three dimentionsããAnd structs/records could be done in some similar fashion.ããI have not worked out the details, but you could probably do a computed CALLãor GOTO if you poked the destination part of a regular CALL or GOTO.ããI think there is a lot of potential here with the addition of a POKE or maybeãEXEC_STR opcode, and possibly (but not necessarily) a couple other opcodes toãsimplify generation of CRC32 "addresses" of variables. The nice thing is, onceãthese building-block op-codes are in, people can come up with clever ways toãuse them _afterwards_, without the SBBS executable having to be changed. Onlyãthe BAJA compiler or a pre-processor would need to be updated to handle theãnew ideas, whatever they were, or the programmer could hand-translate at aãpinch.ããEnough talk from me. What do you think?ãã---ã þ Synchronet þ
telnet://talamasca-bbs.com http://www.talamasca-bbs.comã
From
Digital Man@VERT to
Angus Netfoot on Fri Dec 17 06:17:24 1999
RE: BAJA OpCode suggestionãBY: Angus Netfoot to Digital Man on Thu Dec 16 1999 07:56 pmããI moved the message to DOVE-Net/Baja Programming where it's more "on topic".ã:-)ãã > I've been thinking about it some more.ã > ã > The idea is to allow the programmer to generate code on-the-fly for immediatã > execution without the overhead of writing a .BIN file to disk and thenã > executing it. I figure that means either a POKE of some sort allowing theã > code space to be changed, or an EXEC_STR that allows a sequence of BAJA/SBBSã > instructions in string to be executed. I'm not sure which one is the mostã > suitable there are probably good reasons for and against both.ã > ã > If we could do this, we could look at BAJA operation codes as low-levelã > building blocks, and construct higher-level operations out of them. Theseã > higher-level operations would only need to be known to the BAJA compiler,ã > which would translate any high-level concept into the lower-level codes thatã > SBBS can understand and interpret.ã > ã > If you are going to POKE stuff into the current code-space you probably needã > to say WHAT to poke, WHERE to poke it, and HOW MUCH of it to poke. You mighã > want to poke the least significant 1, 2 or 4 bytes of an integer (or integerã > constant?) or maybe the first 18 bytes of a string (string constant?). Youã > would want to poke relative to your own position, or absolute to the code-ã > space (POKER / POKEA maybe? or with a flag?). So maybe something like:ã > ã > POKE <location> <value> <size> <flags>ã > ã > <flags> might select RELATIVE or ABSOLUTE location, or even something weirdã > like RELATIVE_TO_ABSOLUTE_LABEL so you could POKE at Label+2 or something.ã > You might introduce a Pseudo-Label meaning "Here" so you could poke to $+6ã > or whatever.ã > ã > With <size> defaulted to 4 and <flags> defaulted to maybe RELATIVE then theã > last two would disappear in a lot of cases and the last one in almost allã > cases, so the normal usage would be:ã > ã > POKE <location> <value>ã > ã > As an alternative to the POKE idea, there is EXEC_STR as in something like:ã > ã > EXEC_STR <string to execute> <start offset> <flags>ã > ã > The <flags> parameter could allow you to select whether to execute in theã > current scope or it's own local scopeperhaps? And default to the currentã > scope. The <start offset> would default to zero mostly, I suppose, but wouldã > allow you to jump into the code-string somewhere in the middle.ã > ã > This looks like it could be good. EXEC_STR would allow you to constructã > essentially mini-routines of a few dozen instructions in a string, withoutã > worrying about where each part of each instructions was to be poked to. Butã > there are probably lots of worrysome complications. Recursive EXEC_STRã > operations embedded in a string that you are already EXEC_STR-ing?ã > Performing loops and other branch-type operations within the string beingã > EXEC_STR-ed? Needs thought.ããThe first problem I see with EXEC_STR is the NUL-terminated string issue.ãWouldn't be able to execute an IF_TRUE DO_SOMETHING END_IF, for example. So,ãperhaps an EXEC_BUF with a length argument. sprintf() could still be used toãbuild the buffer however.ããIf I do something like this, creating a CMDSHELL.INC (Baja equivalent forãcmdshell.h) would improve the readability considerably:ãã sprintf str "%c%cTEST\0%c" CS_IF_TRUE CS_PRINT CS_ENDIFã exec_buf str 8ã ã > > Might as well through a peek function in there too, eh? :-)ã > ã > Couldn't hurt, although no immediate use comes to mind... Are you thinking ã > anything specific?ããNope. Just thinking if you can poke somewhere, it might be useful to peek at itãlater (like a data block). Or peek to see if the data hasn't been initializedãor something.ãã > > To make it even more useful, pre-allocated data blocks (in the moduleãcodã > > space, so they could be peeked/poked) would be nice.ã > ã > I'm not sure I get what you are aiming at.ããTo poke data (rather than code), you'll need blocks of code space that can beãsafely written over. There is currently no way to do this other than creating aãblock of RETURNS (or some other unreachable code) at the end of your module (orãsome other place safe).ã ã > > Probably could use a WORD and DWORD variant of peek/poke too.ã > ã > I think that you _do_ need to allow for variable length POKE operations, likã > poking a single or two-byte op-code or a 4-byte operand CRC32 "address". Iã > rather like the idea of being able to poke arbitrary strings of bytes so thaã > you could construct a sequence of instructions using a single SPRINTF orã > something (or even read a string from disk), POKE the entire thing in one goã > and then CALL it, GOTO it, or fall through into it.ããYeah, I see the need for a NOP instruction. :-)ã ã > Hmmm. Some other instructions might be useful to support this, like a way tã > declare a block of space with a label on it maybe? Oh, this is what you meaã > earlier by pre-allocated data blocks. Yes. Good plan.ã > ã > #Hello World the HARD wayã > SPRINTF Some_Str "\x51Hello, World!" # x51 = PRINTã > POKE PokeHere Some_Str 13ã > :PokeHereã > DEF_BYTES 13ã > ã > sort of thing.ã > ã > > That could really open up possiblities to the enterprising programmer.ã > ã > Actually, it's sorta scary! :) Suppose we had the POKE op-code and we agreã > on a notational equivilence for array syntax. Example, suppose we agreed thã > ã > ADD MyArray[Dest] YourArray[Source]ã > ã > is only a notational shorthand forã > ã > ADD MyArray.32 YourArray.Wednesdayã > ã > assuming that Dest = 32 and Source = "Wednesday". Then we could do somethinã > like:ã > ã > INT SAddr # we need theseã > STR IAddr1 IAddr2ã > ã > SPRINTF SAddr "MyArray.%ld" Dest # compute CRC\Address of Destã > STRUPR SAddrã > CRC32 Iaddr1 Saddrã > ã > SPRINTF SAddr "YourArray.%s" Source # compute CRC\Address of Sourceã > STRUPR SAddrã > CRC32 IAddr2 Saddrã > ã > POKE Modify+2 IAddr1 # Modify code-space Destã > POKE Modify+6 IAddr2 # Modify code-space Sourceã > ã > :Modifyã > ADD Dummy Dummy # This is modified by the POKEã > ã > We have just added two array elements together, computing the elements at ruã > time and we have used numeric and non-numeric indexes to boot. And the onlyã > new instruction introduced is the POKE itself.ã > ã > Or instead of poke, you could doã > ã > SPRINTF CodeStr "\x7F\x38%ld%ld" IAddr1 IAddr2 # neat!ã > EXEC_STR CodeStrã > ã > The coding looks awful, but it could be simplified by a few new supportã > operations. Maybe something similar to an SPRINTF that combined it'sã > arguments in some standard way, did a strupr() on the entire thing andã > computed the CRC all in one operation. But this is only icing, becauseã > you could simply change BAJA.EXE to readã > ã > ADD MyArray[Dest] YourArray[Source]ã > ã > and generate the necessary long-hand code invisibly, "behind the scenes" asã > it were. Or you could leave the BAJA compiler alone and let programmersã > develop their own pre-processor.ã > ã > To declare an array,ã > ã > INT Array[10..16] Yours[RED, GREEN, BLUE] X[1..3][A, B, C]ã > ã > could be a notational convenience meaningã > ã > INT Array.10 Array.11 Array.12 Array.13 Array.14 Array.15 Array.16ã > INT Yours.RED Yours.GREEN Yours.BLUEã > INT X.1.A X.1.B X.1.C X.2.A X.2.B X.2.C X.3.A X.3.B X.3.Cã > ã > And either left to the programmer to hand-translate or handled by some sort ã > preprocessor or by BAJA.EXE itself.ã > ã > You could do multiple indexes (multi-dimensional arrays) by a similar procesã > where the "address" of the element could be computed by:ã > ã > SPRINTF SAddr "Array.%ld.%ld.%ld" X Y Z # three dimentionsã > ã > And structs/records could be done in some similar fashion.ã > ã > I have not worked out the details, but you could probably do a computed CALLã > or GOTO if you poked the destination part of a regular CALL or GOTO.ã > ã > I think there is a lot of potential here with the addition of a POKE or maybã > EXEC_STR opcode, and possibly (but not necessarily) a couple other opcodes tã > simplify generation of CRC32 "addresses" of variables. The nice thing is, oã > these building-block op-codes are in, people can come up with clever ways toã > use them _afterwards_, without the SBBS executable having to be changed. Onã > the BAJA compiler or a pre-processor would need to be updated to handle theã > new ideas, whatever they were, or the programmer could hand-translate at aã > pinch.ã > ã > Enough talk from me. What do you think?ããNOP, POKE and PEEK could do a lot. A data buffer is probably not necessary ifãyou could just label a group of NOPs (perhaps a Baja function to simplify theãsyntax, however), but it should be made clear to programmers that a block ofãbytes defined in that manner are CODE bytes and if they're to be used as data,ãproper precautions should be taken to avoid inadvertent execution.ããEXEC_BUF could be pretty cool too, but would require more work in SBBS.EXE.ãSince you can't "insert" opcodes into the current module image, it would haveãto create a temporary module image to execute the buffer. While it would beãfaster and more convenient than creating .BIN files on the fly, it would inãreality be a very similar implementation.ããSince NOP/POKE/PEEK have the most flexibility, I'll code them first and leaveãEXEC_BUF for a later effort.ããCombining SPRINTF, STRUPR, and CRC32 into a single function is probably notãvery realistic (at least at the PCMS level). A combined STRUPR/CRC32 is aãno-brainer and is a good idea (CRC32UPR?). It would leave the original variableãcase intact too.ããThanks for the suggestions.ããRobã---ã þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.netã
From
Angus Netfoot@VERT/TALAMASC to
Digital Man on Mon Jan 3 00:24:00 2000
RE: BAJA OpCode suggestionãBY: Digital Man to Angus Netfoot on Fri Dec 17 1999 02:17 pmãã > > As an alternative to the POKE idea, there is EXEC_STR as in somethingã > > like:ã > >ã > > EXEC_STR <string to execute> <start offset> <flags>ã >ã > The first problem I see with EXEC_STR is the NUL-terminated string issue.ã > Wouldn't be able to execute an IF_TRUE DO_SOMETHING END_IF, for example.ã > So, perhaps an EXEC_BUF with a length argument. sprintf() could still beã > used to build the buffer however.ãã:) I never thought of the null-byte problem. EXEC_BUF sounds like an idealãway to circumvent it. There may be other problems that have not come to mindãas yet. I have been thinking about POKE for a while, but the EXEC_BUF idea isãa relatively new one here.ããSome things will have to be decided. For example, if, within your buffer youãcode something likeãã GOTO My_LabelããWould that refer to My_Label _within_ the buffer, or to a My_Label outsideãthe buffer and within the calling module? Declaring My_Label within aãbuffer itself is probably tricky, so maybe I should have usedãã GOTO 45 # offset 45ããinstead of a named label. Anyway, you get my point. If you have an END_CMDãin a buffer that you EXEC_BUF, should there also be a CMD_HOME in that bufferãor will it refer to a CMD_HOME in the calling module?ãã > If I do something like this, creating a CMDSHELL.INC (Baja equivalent forã > cmdshell.h) would improve the readability considerably:ã >ã > sprintf str "%c%cTEST\0%c" CS_IF_TRUE CS_PRINT CS_ENDIFã > exec_buf str 8ããThat would certainly be easier than having to look up the hex for each opcodeãyou planned to use. I used to program the Z80 in hex from memory, but thatãwas a loonnng time ago!ãã > NOP, POKE and PEEK could do a lot. A data buffer is probably not necessaryã > if you could just label a group of NOPs (perhaps a Baja function toã > simplify the syntax, however), but it should be made clear to programmersã > that a block of bytes defined in that manner are CODE bytes and if they'reã > to be used as data, proper precautions should be taken to avoid inadvertentã > execution.ããYes, this would allow a lot of extra flexibility with a relative minimum ofãnew opcodes for you to implement. BAJA Programmers would then have theãability to very forcefully shoot themselves in the foot, and will have toãtake all the usual precautions against doing so. :)ãã > EXEC_BUF could be pretty cool too, but would require more work in SBBS.EXE.ã > Since you can't "insert" opcodes into the current module image, it wouldã > have to create a temporary module image to execute the buffer. While itã > would be faster and more convenient than creating .BIN files on the fly,ã > it would in reality be a very similar implementation.ããI imagined that this was the more difficult approach. If you set up aãseparate module image, can it still resolve the variables in the callingãmodule as local? Or would it have to refer to them as GLOBAL INT/STR as perãa separate .BIN file? I suspect that a module calling EXEC_BUF to manipulateãit's own (IOW the callers) variables is likely to be a fairly common theme.ããIf you use a separate module image, that answers my questions WRT the useãof CMD_HOME and CMD_END and similar matters.ãã > Since NOP/POKE/PEEK have the most flexibility, I'll code them first andã > leave EXEC_BUF for a later effort.ããI am keen to see it in action! Err... What were you thinking of doing WRTãthe addressing of the PEEKed/POKEd data? At or relative to a label?ãã > A combined STRUPR/CRC32 is a no-brainer and is a good idea (CRC32UPR?).ã > It would leave the original variable case intact too.ããNot essential at all, but might ease things for the BAJA programmer a bit.ãYou could call it VAR_ADDR or something like that, since it essentiallyãcomputes the "address" of a variable, but CRC32UPR is probably better,ãsince there is no reason not to use it for other purposes that areãunrelated to addressing variables.ãã---ã þ Synchronet þ
telnet://talamasca-bbs.com http://www.talamasca-bbs.comã