Tim Hamilton Posted June 14, 2020 Share Posted June 14, 2020 (edited) Hi, all, I'm practicing assembly language with the Editor/Assembler, using the xdt99 cross-assembler with Emacs on a Mac and running it on js99er.net for the emulator. So far, everything has gone very smoothly...but this one weird bug: If I have a period in a TEXT directive string, I get unpredictable VDP results when I display it using VMBW. For example, I printed my name to the screen (along with some other text), with the text set as: MSG2 TEXT 'Timothy S. Hamilton' The other strings printed to the screen just fine with VMBW, but this one came up with the last byte displayed as a space: Timothy S. Hamilto Thinking I'd miscounted the bytes by one, I tried other combinations of characters. It turned out it was the period causing the problem. Later, after putting it back in, sending this same string to VMBW caused the screen to flash with colored noise. Another time, it made it go blank, with a solid color on the border. [Edit: It was another version of the string that caused the flashing, with one or two characters changed, but with the period still there. I haven't tried replicating that particular behavior since then.] I thought it might be some glitch in encoding the period, so I opened up my assembly source file in E/A directly and put the period in there. It displayed the period just fine. Does anybody have a suggestion as to what might be causing this and how to get around it? Edited June 14, 2020 by Tim Hamilton 1 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted June 14, 2020 Share Posted June 14, 2020 Did you try to produce a list file and look at the string in that? 1 Quote Link to comment Share on other sites More sharing options...
ralphb Posted June 14, 2020 Share Posted June 14, 2020 Could you perhaps post your source file with the bad dot in it? I did a quick test, and there's nothing unusual with dots on my system. 1 Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted June 14, 2020 Share Posted June 14, 2020 You may need to put an "EVEN" after the 'Timothy S. Hamilton' which is 19 bytes long. If the assembler has trouble with the period you could do this: TEXT 'Timothy S' BYTE >2E TEXT ' Hamilton' 1 Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 14, 2020 Author Share Posted June 14, 2020 4 hours ago, ralphb said: Could you perhaps post your source file with the bad dot in it? I did a quick test, and there's nothing unusual with dots on my system. OK, I've pared it down to a minimal program that shows the bug, and I have found that the placement of the period makes a difference, so I am posting two versions. test7.asm prints the string 'X.' without a problem. test8.asm should print the string '.X', but the screen remains blank. Here is test7.asm first. It's my first time posting code, and I don't know the right formatting in this window, so I'm quoting it. Quote * Minimal program to test bug with '.' DEF START REF VMBW STATUS EQU >837C SAVRTN DATA >0000 MSG1 TEXT 'X.' MGLN1 EQU 2 MESSAGE 1 LENGTH MGLC1 EQU 0 MESSAGE 1 SCREEN LOCATION WSPREG BSS >20 * START OF PROGRAM START MOV R11,@SAVRTN LWPI WSPREG LI R0,MGLC1 PRINT MESSAGE 1 LI R1,MSG1 LI R2,MGLN1 BLWP @VMBW MOV @SAVRTN,R11 CLR @STATUS DECT R11 RT END Now I'll post test8.asm: Quote * Minimal program to test bug with '.' DEF START REF VMBW STATUS EQU >837C SAVRTN DATA >0000 MSG1 TEXT '.X' MGLN1 EQU 2 MESSAGE 1 LENGTH MGLC1 EQU 0 MESSAGE 1 SCREEN LOCATION WSPREG BSS >20 * START OF PROGRAM START MOV R11,@SAVRTN LWPI WSPREG LI R0,MGLC1 PRINT MESSAGE 1 LI R1,MSG1 LI R2,MGLN1 BLWP @VMBW MOV @SAVRTN,R11 CLR @STATUS DECT R11 RT END The DECT R11 near the end is something I got from Molesworth's Introduction to Assembly Language for the TI Home Computer, for freezing screen output in his tutorial programs. The list output for the two is identical, except for the order of the two bytes in the string. I've done a diff to confirm, but I'll post both here, in case there's something subtle I missed. test7.lst: Quote XAS99 CROSS-ASSEMBLER VERSION 3.0.0 **** **** > test7.asm 0001 * Minimal program to test bug with '.' 0002 DEF START 0003 REF VMBW 0004 837C STATUS EQU >837C 0005 0000 0000 SAVRTN DATA >0000 0006 0002 582E MSG1 TEXT 'X.' 0007 0002 MGLN1 EQU 2 MESSAGE 1 LENGTH 0008 0000 MGLC1 EQU 0 MESSAGE 1 SCREEN LOCATION 0009 0004 WSPREG BSS >20 0010 * START OF PROGRAM 0011 0024 C80B 38 START MOV R11,@SAVRTN 0026 0000r 0012 0028 02E0 18 LWPI WSPREG 002A 0004r 0013 002C 0200 20 LI R0,MGLC1 PRINT MESSAGE 1 002E 0000 0014 0030 0201 20 LI R1,MSG1 0032 0002r 0015 0034 0202 20 LI R2,MGLN1 0036 0002 0016 0038 0420 54 BLWP @VMBW 003A 0000e 0017 003C C2E0 34 MOV @SAVRTN,R11 003E 0000r 0018 0040 04E0 34 CLR @STATUS 0042 837C 0019 0044 064B 14 DECT R11 0020 0046 045B 20 RT 0021 END **** **** > vmbw_ea.asm 0001 * VDP multi-byte write, where length can be zero 0002 0003 def vmbw 0004 ref vdpwa, vdpwd 0005 0006 even 0007 0008 vmbw: 0009 0000 2094 data >2094 0010 0002 0004r data !vmbw 0011 0012 !vmbw: 0013 0004 D82D 54 movb @1(r13), @vdpwa 0006 0001 0008 0000e 0014 000A C01D 26 mov *r13, r0 0015 000C 0260 22 ori r0, >4000 000E 4000 0016 0010 D800 38 movb r0, @vdpwa 0012 0000e 0017 0014 C06D 34 mov @2(r13), r1 0016 0002 0018 0018 C0AD 34 mov @4(r13), r2 001A 0004 0019 0020 001C 1002 14 jmp !dec 0021 001E D831 48 !mov movb *r1+, @vdpwd 0020 0000e 0022 0022 0602 14 !dec dec r2 0023 0024 18FC 14 joc -!mov 0024 0025 0026 0380 18 rtwp And for test8.asm: Quote XAS99 CROSS-ASSEMBLER VERSION 3.0.0 **** **** > test8.asm 0001 * Minimal program to test bug with '.' 0002 DEF START 0003 REF VMBW 0004 837C STATUS EQU >837C 0005 0000 0000 SAVRTN DATA >0000 0006 0002 2E58 MSG1 TEXT '.X' 0007 0002 MGLN1 EQU 2 MESSAGE 1 LENGTH 0008 0000 MGLC1 EQU 0 MESSAGE 1 SCREEN LOCATION 0009 0004 WSPREG BSS >20 0010 * START OF PROGRAM 0011 0024 C80B 38 START MOV R11,@SAVRTN 0026 0000r 0012 0028 02E0 18 LWPI WSPREG 002A 0004r 0013 002C 0200 20 LI R0,MGLC1 PRINT MESSAGE 1 002E 0000 0014 0030 0201 20 LI R1,MSG1 0032 0002r 0015 0034 0202 20 LI R2,MGLN1 0036 0002 0016 0038 0420 54 BLWP @VMBW 003A 0000e 0017 003C C2E0 34 MOV @SAVRTN,R11 003E 0000r 0018 0040 04E0 34 CLR @STATUS 0042 837C 0019 0044 064B 14 DECT R11 0020 0046 045B 20 RT 0021 END **** **** > vmbw_ea.asm 0001 * VDP multi-byte write, where length can be zero 0002 0003 def vmbw 0004 ref vdpwa, vdpwd 0005 0006 even 0007 0008 vmbw: 0009 0000 2094 data >2094 0010 0002 0004r data !vmbw 0011 0012 !vmbw: 0013 0004 D82D 54 movb @1(r13), @vdpwa 0006 0001 0008 0000e 0014 000A C01D 26 mov *r13, r0 0015 000C 0260 22 ori r0, >4000 000E 4000 0016 0010 D800 38 movb r0, @vdpwa 0012 0000e 0017 0014 C06D 34 mov @2(r13), r1 0016 0002 0018 0018 C0AD 34 mov @4(r13), r2 001A 0004 0019 0020 001C 1002 14 jmp !dec 0021 001E D831 48 !mov movb *r1+, @vdpwd 0020 0000e 0022 0022 0602 14 !dec dec r2 0023 0024 18FC 14 joc -!mov 0024 0025 0026 0380 18 rtwp Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 14, 2020 Author Share Posted June 14, 2020 There's another interesting behavior I found with this. In the full version of the program, I am using VSBW to fill the screen with asterisks before I use VMBW to write the string to the display. When the buggy string is present, it clears the asterisks from the screen entirely. Here's a version that shows this behavior, where the string is '.X'. Nothing shows up on the screen by the time it freezes output. When I reverse the string to 'X.', it does what I expect: it displays 'X.' on a background of asterisks. (I'll note that as I'm learning more assembly, I've realized that I should have used more EQU's and fewer DATA statements to save space, so this is not the most efficient program.) Quote * Minimal program to test bug with '.' DEF START REF VMBW STATUS EQU >837C SAVRTN DATA >0000 MSG1 TEXT 'Timothy . Hamilton' MGLN1 EQU 18 MESSAGE 1 LENGTH MGLC1 EQU 391 MESSAGE 1 SCREEN LOCATION (R13 C7) WSPREG BSS >20 * START OF PROGRAM START MOV R11,@SAVRTN LWPI WSPREG LI R0,MGLC1 PRINT MESSAGE 1 LI R1,MSG1 LI R2,MGLN1 BLWP @VMBW MOV @SAVRTN,R11 CLR @STATUS DECT R11 RT END [Rebecca:~/TI Computer/ti-asm] timhamilton% rm test6.asm [Rebecca:~/TI Computer/ti-asm] timhamilton% cat test6.asm DEF START REF VSBW,VMBW STATUS EQU >837C * VARIABLES SAVRTN DATA >0000 STRV DATA 0 STARTING SCREEN LOC ENDV DATA 768 (ENDING SCREEN LOC) + 1 CHAR1 DATA >2A00 "*" CHAR2 DATA >2000 " " MSG1 TEXT '.X' MGLN1 EQU 2 MGLC1 EQU 391 MSG1 SCREEN LOCATION (R13 C7) WSPREG BSS >20 * START OF PROGRAM START MOV R11,@SAVRTN LWPI WSPREG MOV @ENDV,R5 USE R5 FOR ENDING SCREEN LOCATION. MOV @STRV,R0 STARTING SCREEN LOCATION MOV @CHAR1,R1 "*" MOST SIGNIFICANT BYTE IS ASCII CODE * LOOP: INCREMENT SCREEN LOCATION & PRINT "*" LOOP BLWP @VSBW SEND CHARACTER TO VDP INC R0 INCREMENT SCREEN LOCATION C R0,R5 ARE WE AT THE END LOCATION? JEQ PNTMSG IF SO, GO TO PRINT MESSAGE JMP LOOP OTHERWISE, GO AGAIN PNTMSG LI R0,MGLC1 PRINT MESSAGE 1 LI R1,MSG1 LI R2,MGLN1 BLWP @VMBW * CLEAN UP AND FINISH THE PROGRAM FINISH MOV @SAVRTN,R11 CLR @STATUS DECT R11 RT END Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 14, 2020 Author Share Posted June 14, 2020 6 hours ago, Asmusr said: Did you try to produce a list file and look at the string in that? Hi, Asmusr, Thanks for the suggestion. I've now posted the list file in my first reply above. It shows the correct bytes for the ASCII. When I reorder the characters in the string ('X.' vs. '.X'), the bytes are reordered properly, and I can see no other differences. I'm not experienced enough to know what else I can catch in the list file, but I can produce a working version and a buggy version, and the list files show that the only difference between them is the order of the bytes in that string. Is that a good way to use the list file for debugging? Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 14, 2020 Author Share Posted June 14, 2020 1 hour ago, senior_falcon said: You may need to put an "EVEN" after the 'Timothy S. Hamilton' which is 19 bytes long. If the assembler has trouble with the period you could do this: TEXT 'Timothy S' BYTE >2E TEXT ' Hamilton' On the odd number of bytes in the string: In working up a minimal buggy example to post here, I found that it still occurs with an even number. In the two examples I posted above, I used the strings 'X.' (fine) and '.X' (buggy). I'll try your suggestion of using the BYTE to insert a period. That's a really clever idea. If we can't find what's causing the bug, at least I could work around it with this. 1 Quote Link to comment Share on other sites More sharing options...
ralphb Posted June 14, 2020 Share Posted June 14, 2020 OK, let's try to rule out a few things. Could you please add a LIMI 0 at START, and then replace DECT R11 and RT by JMP $? What's the result now? 2 Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 14, 2020 Author Share Posted June 14, 2020 3 hours ago, ralphb said: OK, let's try to rule out a few things. Could you please add a LIMI 0 at START, and then replace DECT R11 and RT by JMP $? What's the result now? OK, Ralph, I've done that. Let me post the new version to make sure that I put the LIMI 0 in exactly the right place, since I haven't used it before: Quote * Minimal program to test bug with '.' DEF START REF VMBW STATUS EQU >837C SAVRTN DATA >0000 MSG1 TEXT '.X' MGLN1 EQU 2 MESSAGE 1 LENGTH MGLC1 EQU 0 MESSAGE 1 SCREEN LOCATION WSPREG BSS >20 * START OF PROGRAM START LIMI 0 MOV R11,@SAVRTN LWPI WSPREG LI R0,MGLC1 PRINT MESSAGE 1 LI R1,MSG1 LI R2,MGLN1 BLWP @VMBW MOV @SAVRTN,R11 CLR @STATUS JMP $ END So the JMP $ sets up a single-instruction loop, I see. That looks much better than Molesworth's trick (DECT R11) that I had ended with. The result is the same as the buggy version earlier: When I use the string 'X.', it prints to the screen. When I use '.X', the screen goes blank. Quote Link to comment Share on other sites More sharing options...
senior_falcon Posted June 14, 2020 Share Posted June 14, 2020 (edited) Here's a way to see if the assembler is messing up the string somehow when it sees a period. AORG >A000 TEXT '123.456' TEXT 'TESTING' END Assemble and load, then use Classic99's debugger to look at CPU ram at >A000. You should see "123.456TESTING" Also, you could try assembling your program with the TI assembler to see if it behaves properly. (Edit) I don't know if there is a debugger in JS99er. If not you can load my 2 line program from TI BASIC with the E/A cartridge, then CALL PEEK starting at -24576 to see what is there. Edited June 14, 2020 by senior_falcon 1 Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 14, 2020 Author Share Posted June 14, 2020 7 hours ago, senior_falcon said: You may need to put an "EVEN" after the 'Timothy S. Hamilton' which is 19 bytes long. If the assembler has trouble with the period you could do this: TEXT 'Timothy S' BYTE >2E TEXT ' Hamilton' Well, here's something funny—I tried out your trick, and it gave the same bug! In keeping with the minimal version I've pared it down to, I made the changes suggested by ralphb above (LIMI 0 and JMP $), and I set the message to '.X' this way: Quote MSG1 BYTE >2E TEXT 'X' Result is again a blank screen. If I enter this directly in the emulated Editor/Assembler program in js99er.net, it runs just fine. I have produced a listing from both the version I entered into E/A and from the version I assembled with xas99.py, and as far as I can tell, they're identical. (One question on listings, though: what do 'r' and 'e' mean when appended machine code words? In E/A's listing, 'r' corresponds to a single quote, and there's nothing corresponding to the 'e'.) Quote Link to comment Share on other sites More sharing options...
Stuart Posted June 15, 2020 Share Posted June 15, 2020 2 hours ago, Tim Hamilton said: (One question on listings, though: what do 'r' and 'e' mean when appended machine code words? In E/A's listing, 'r' corresponds to a single quote, and there's nothing corresponding to the 'e'.) They indicate unresolved references - their value is not known until the program is loaded by the loader. What happens if you move the TEXT line to the end of the program - immediately before the END statement? Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 15, 2020 Author Share Posted June 15, 2020 27 minutes ago, Stuart said: They indicate unresolved references - their value is not known until the program is loaded by the loader. What happens if you move the TEXT line to the end of the program - immediately before the END statement? Hey, it worked! Thanks, Stuart. Why would this be the case? Here's the source code for this version: Quote DEF START REF VMBW STATUS EQU >837C SAVRTN DATA >0000 MGLN1 EQU 2 MESSAGE 1 LENGTH MGLC1 EQU 0 MESSAGE 1 SCREEN LOCATION WSPREG BSS >20 * START OF PROGRAM START LIMI 0 MOV R11,@SAVRTN LWPI WSPREG LI R0,MGLC1 PRINT MESSAGE 1 LI R1,MSG1 LI R2,MGLN1 BLWP @VMBW MOV @SAVRTN,R11 CLR @STATUS JMP $ MSG1 BYTE >2E TEXT 'X' END And it works using either Quote MSG1 BYTE >2E TEXT 'X' or Quote MSG1 TEXT '.X' Now: Why would it work when it's put at the end? Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 15, 2020 Author Share Posted June 15, 2020 5 hours ago, senior_falcon said: (Edit) I don't know if there is a debugger in JS99er. If not you can load my 2 line program from TI BASIC with the E/A cartridge, then CALL PEEK starting at -24576 to see what is there. OK, thanks for the idea. I think there is a debugger in js99er; I'll have to poke around and learn how to use it. But your alternative plan is doable, too. Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted June 15, 2020 Share Posted June 15, 2020 Just out of curiosity, what steps are you following to assemble and then load the file into js99er (where I assume you are using the Ea cart load/run option)? would be interesting to see the object files for the good and bad .X / X. source. Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 15, 2020 Author Share Posted June 15, 2020 23 minutes ago, InsaneMultitasker said: Just out of curiosity, what steps are you following to assemble and then load the file into js99er (where I assume you are using the Ea cart load/run option)? would be interesting to see the object files for the good and bad .X / X. source. I'm composing on Emacs running on a Mac, then assembling it with ralphb's xdt99 cross-assembler suite (I use the Emacs assembly environment that comes with xdt99). The specific commands I use to assemble it ("test11.asm" in this case) and then add to the working disk are: Quote > ../xdt99-master/xas99.py -R -i test11.asm vmbw_ea.asm > ../xdt99-master/xdm99.py work1.dsk -a test11.img Then on js99er, I load the E/A disk A into disk drive 1 and the working disk into disk drive 2. In E/A, I select option 5: Run Program File, and the program runs automatically on loading. 1 Quote Link to comment Share on other sites More sharing options...
+InsaneMultitasker Posted June 15, 2020 Share Posted June 15, 2020 11 hours ago, Tim Hamilton said: Then on js99er, I load the E/A disk A into disk drive 1 and the working disk into disk drive 2. In E/A, I select option 5: Run Program File, and the program runs automatically on loading. Can you share a .dsk with the working and non working programs? No longer needed; see explanations below. Quote Link to comment Share on other sites More sharing options...
ralphb Posted June 15, 2020 Share Posted June 15, 2020 6 hours ago, Stuart said: They indicate unresolved references - their value is not known until the program is loaded by the loader. What happens if you move the TEXT line to the end of the program - immediately before the END statement? Not quite, e stands for "external", i.e., unresolved reference, and r stands for "relocatable". 2 Quote Link to comment Share on other sites More sharing options...
ralphb Posted June 15, 2020 Share Posted June 15, 2020 (edited) I didn't know you were building E/A 5 images. For those images, the first word must be an executable statement, but in your case, it's >0000. Funny that it's doing anything at all. Maybe it's just skipping the 0, and then it tries to execute your '.X'/'X.', which of course would do different things. '.X' is XOP *r8, r9, and 'X.' is SZCB @>0000(R14), @>0000 (since there 0's following). As suggested, move your text further down (not necessarily the end of the program), and make sure START is the first word in your program (it could well be a JMP or B). Whew! ? EDIT: Just tested it: The CPU will indeed just skip over >0000. The next question would be if >1000 or >0000 is faster ... ? Edited June 15, 2020 by ralphb 3 Quote Link to comment Share on other sites More sharing options...
Tursi Posted June 15, 2020 Share Posted June 15, 2020 hehe... all illegal opcodes are NOPs with a 6 cycle instruction time... so technically faster 2 Quote Link to comment Share on other sites More sharing options...
Tim Hamilton Posted June 15, 2020 Author Share Posted June 15, 2020 (edited) 7 hours ago, ralphb said: I didn't know you were building E/A 5 images. For those images, the first word must be an executable statement, but in your case, it's >0000. Funny that it's doing anything at all. Maybe it's just skipping the 0, and then it tries to execute your '.X'/'X.', which of course would do different things. '.X' is XOP *r8, r9, and 'X.' is SZCB @>0000(R14), @>0000 (since there 0's following). As suggested, move your text further down (not necessarily the end of the program), and make sure START is the first word in your program (it could well be a JMP or B). Whew! ? EDIT: Just tested it: The CPU will indeed just skip over >0000. The next question would be if >1000 or >0000 is faster ... ? OK, that makes sense to me, even with what little I know so far. Let me see if I understand: So as assembler directives, DEF, REF, and EQU don't produce words in the object file, but the DATA, TEXT, and BYTE statements do, and because they preceded START, the computer tried to execute these as machine code. So what I should do is either move my DATA, TEXT, and BYTE statements to near the end, or start the program something like this: Quote DEF START REF VMBW START JMP BEGIN STATUS EQU >837C SAVRTN DATA >0000 MSG1 TEXT '.X' WSPREG BSS >20 BEGIN MOV R11,@SAVRTN etc. Would that be a good structure? What approach do you prefer for your own code? I see now why I was getting the program to work fine if I entered it in E/A directly: I was choosing option 3: Load and Run, rather than option 5. But why do (improperly structured) programs work differently between these two options? Thanks a whole lot for the help, @ralphb, and the rest of y'all, too. This has taught me a lot about assembly language, in addition to fixing my mistake. Thanks especially for creating the xdt99 tools. Those have made it much easier to create my programs, so I can use a modern editor. Thanks also to @Asmusr for creating js99er, which I'm using for all of my TI work until I get my actual TI's video glitch fixed. Edited June 15, 2020 by Tim Hamilton Misread ralphb's discussion of machine code 1 Quote Link to comment Share on other sites More sharing options...
ralphb Posted June 15, 2020 Share Posted June 15, 2020 22 minutes ago, Tim Hamilton said: Would that be a good structure? What approach do you prefer for your own code? I see now why I was getting the program to work fine if I entered it in E/A directly: I was choosing option 3: Load and Run, rather than option 5. But why do (improperly structured) programs work differently between these two options? Your new program will work. Personally, I keep all my constants at the end of the program, followed by COPYs, but occasionally I put constants near where they are used, in particular branch tables. E/A 3 starts a program by branching to the symbol you enter after the filename, which can be anywhere in the program. It's only E/A 5 that has this restriction about the first word, even cartridges let you start anywhere. 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.