Jump to content
IGNORED

Editor/Assembler bug with '.' using xdt99 cross-assembler & js99er


Tim Hamilton

Recommended Posts

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 by Tim Hamilton
  • Confused 1
Link to comment
Share on other sites

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

 

 

Link to comment
Share on other sites

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

 

 

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by senior_falcon
  • Like 1
Link to comment
Share on other sites

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'.)

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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".

  • Like 2
Link to comment
Share on other sites

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 by ralphb
  • Like 3
Link to comment
Share on other sites

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 by Tim Hamilton
Misread ralphb's discussion of machine code
  • Like 1
Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...