yesterday, while reporting on my success with the LIST command, i noted that i was going to try to add the byte values in front of the disassembled commands. well, that’s done now too…
as noted, the output of LIST is now formatted thusly:
$aaaa: bb cc dd mmm <addr>
with ‘aaaa’ being the address of the instruction being disassembled, ‘bb’ (and ‘cc’ and possibly ‘dd’ if needed) are the actual byte values that form the command. ‘mmm’ is the 3-letter mnemonic for the command, and ‘<addr>’ is the addressing or argument info if appropriate.
so all of the memory-related commands for the 8-bit project are now complete and working. the remaining baseline commands to be implemented are all storage related – loading/saving files and so forth. since i don’t have the filesystem completely designed yet, i probably won’t be writing any more code for a bit. just as i feel like i’ve really gotten the hang of it and enjoying it, too… 8(
i finally completed the LIST command for the 8-bit project by adding argument printing. getting the branch address calculation correct held me back for a week, but fell quickly when i finally realized that a backward branch was actually the same calculation as a forward branch, just with a pre-decrement of the MSB to account for crossing page boundaries. i had been trying to use a different code path for it, subtracting rather than adding, etc.
for the mnemonics themselves, i set up a 1024-byte table – 4 bytes for each of the 256 possible values. the first three bytes of each entry are the three-character opcode (or ??? for illegal opcodes) and the fourth byte is the address mode. this allows me to simply use the actual opcode (multiplied by 4) as an index into the table. the address mode byte is similarly used as an index into a table of jump addresses for each of the address mode output handlers. i’m sure all of that could have been done in some fancy way that would save a lot of memory (at the expense of extra clock cycles), but as i’ve mentioned several times, i’m aiming for something that works right now rather than the most elegant solution.
i did add a bit of elegance by clearing the screen before i start outputting. this prevents the lcd from having to scroll, which is a fairly slow operation. so the output is not only complete now, but it finishes faster and looks better while it’s outputting. 8)
for the next step, i think i’m going to improve LIST a bit more by adding the actual byte values to the output, i.e. instead of the output being
$aaaa: mmm <addr>
it will instead become
$aaaa: aa bb cc mmm <addr>
where of course ‘bb’ and ‘cc’ may actually be just spaces depending on the number of bytes that the command actually uses. this will bring the maximum length of a line up from 23 to 32-34 characters (depending on how wide i make the gaps), which is not a problem for my 40-character-wide lcd.
i’ve decided to work on the LIST command rather than the hardware on the 8-bit project. the LIST command shows a disassembly of several instructions, equivalent to the ‘L’ command in the apple 2 monitor. so i’ve had some pretty good success this morning – i’m able to output the address and 3-letter opcode mnemonic. no argument printing yet, but that’s next.
command format is
as usual, the address argument is optional. if omitted, listing will start at the address byte following the end of the previous LIST. this allows the user, after an initial LIST command with address, to simply continue hitting return to show additional pages of disassembly.
output format for each line is
aaaa: mmm [args]
where ‘aaaa’ is the 4-hex-character address of the instruction, ‘mmm’ is the 3-character opcode mnemonic, and [args] is the arguments for the opcode as appropriate. arguments will be displayed in the same format as the apple 2’s disassembly listing, e.g.” (zz),X” or “#$xx”.
since i’m using an LCD with 8 lines of text, only 7 lines of disassembly can be shown at once. the eighth line is needed for the prompt for the next command line.
just finished tested the SET command for the 8-bit project, which sets the contents of memory to new values and takes the form
SET [A$xxxx,] aa bb cc…
where as usual square brackets indicate that the address parameter is optional, and (if present) the address must be 4 hex characters long and followed by a separating comma. if the address parameter is omitted, then input begins at the current address. If the previous command was SET, this is the byte after the last byte modified by the previous SET command. If the previous command was SHOW, this is the byte after the last byte shown.
after the comma, the byte values to be set are entered in hex. each byte must be two hex characters long and separated from the next byte by a space. the number of bytes entered in a single SET command is limited only by the 255 character limit on the length of an input line (not 256 because the 256th character will be the CR). so this allows you to enter up to ~80 bytes with a single command.
as i’ve mentioned previously, the ‘A’ is actually completely optional at this point – i scan directly for the ‘$’ to look for an address parameter. so in reality, you could enter something like
SET adfsa8093ja;klncvd$1000,01 02 03
and the code would set the 3 bytes starting at $1000 to 01, 02, and 03 without issuing any error message. i’ll work at making it stricter once everything is working. (although, at least for the basic set of commands, i think i’m actually approaching that point…)
not sure where i’ll go next. other than the disk commands, the only primary command left is LIST, which is intended to provide a full disassembly of several lines of code starting at the target address.
just finished testing the MOVE command for the 8-bit project, which copies a block of memory from one location to another, and takes the form
where S is the Source address, D is the destination address, and L is the length of the block to copy. as usual the addresses and length must each be exactly 4 hex characters long. note that the S/D/L characters are, strictly speaking, optional. i locate hex arguments by searching only for the $ and then looking at the next four characters. i know this is a bit of a shortcut, but it works for now. if/when everything is working, i can go back and be more strict about such things.
memory is copied in full 256-byte pages, plus a final partial page if needed. full pages are copied top to bottom, i.e. starting at offset 0x00 and going to 0xFF. the partial page, by contrast, is copied bottom to top, i.e. starting at offset 0xzz and going to 0x00. i did this because it allows me to use the LSB of the stored length parameter as both the counter and the offset index for the LDA/STA commands.
note that their is no argument checking done – so if xxxx < yyyy < xxxx + zzzz, part of the memory to be copied will be overwritten, possibly before it has been copied. this would obviously lead to unexpected results, and should be avoided. at some point in the future i hope to improve this function to detect such cases and change the order of the move to produce the intended results.
so, about that bug…as i was debugging MOVE, i found a bug in SHOW (which i was using to verify whether MOVE was working correctly). The bug was that SHOW would not allow a hex character ‘F’ in its address argument. however, the actual error traced back to the function that converts command line arguments into hex values, meaning that, in reality, NO function would allow an ‘F’ in their arguments.
the cause of the bug is that, in trying to determine if the character i had pulled from the input buffer was a legal hex character, i was doing a CMP #0x0F; BPL err. however, zero is considered to be positive, so an ‘F’ would cause a branch to an error condition. but because i was never setting an error code, no error message was generated – it just returned to the input prompt.
the fix was simple – change the CMP #0x0F to CMP 0x10, so that an ‘F’ now goes to -1 and the BPL branches properly.
just did the final testing on the SHOW command – having it print out the next 8 bytes if a blank line is entered and SHOW was the most recent command. again, my goal here was to emulate how the apple monitor works, allowing the user to see successive 8-byte chunks without having to enter any additional keystrokes beyond the ‘return’.
next, i’m trying to choose between implementing the XMIT command (transmit data over the serial port) or the SET command (set memory contents). i don’t have a strong preference for either right now, though i think XMIT makes sense because that should also spur me to work on integrating my own serial port hardware onto the breadboard, which is the last apple-based hardware that i need to get working before i can move off to my own full hardware.
that also brings up the matter that i need to get to work on designing the full hardware schematic, then laying out the pcb(s), getting those manufactured, etc. so hopefully i’ll be posting something soon on my thoughts on that…
another day, another success 8)
yesterday i successfully tested the SHOW command for the 8-bit project, which shows the contents of memory, and takes the form
where as usual square brackets indicate that the address parameter is optional, and (if present) the address must be 4 hex characters long. if the address parameter is omitted, then output begins from the byte after the last byte show by the last SHOW command.
format of the output is
xxxx:yy yy yy yy yy yy yy yy
where ‘xxxx’ is the address of the first byte. up to 8 bytes are shown; the loop exits when the address of the next byte to be shown is an exact multiple of 8. this makes understanding the data a little easier, since each (sans argument) SHOW after the first will always show 8 bytes and start at either xxx0 or xxx8. you might recognize that this is very similar to how the apple monitor works when displaying data, and that was in fact my model.
there is one more functionality to be written and tested for SHOW, and that is the ability for the system to remember the last command entered, and then if the user hits ‘enter’ on an empty line and the last command was SHOW, to respond as if the user had entered SHOW without an argument. this will better match the apple case, where continually hitting ‘enter’ will display the next 8 bytes, allowing the user to display regions of memory 8 bytes at a time without having to type SHOW each time.
i’m not sure where i’ll go next…i need to start designing and building the real hardware at some point, and i’m just about at the point where i have the software ready for that. on the other hand, the serial port code currently uses the super serial card, which obviously won’t be available in my design (although i will be using a 6551 chip pulled from an SSC). so it would be good to get that set up on the breadboard, update the code, and test it before moving to final hardware.