Jump to content
  • entries
    45
  • comments
    10
  • views
    10,339

Dealer Demo, part 6: Less is More


Atari_Ace

511 views

We resume our disassembly of the Dealer Demo and find the next four Forth words, 0= and 0<, and then unexpectedly U< and <.

-def  WORD     NFA   PFA    same as fig-Forth?
10A7  0=       L605  ZEQU   Yes
10BC  0<       L619  ZLESS  Yes
10CE  U<       L1246 ULESS  No
10EB  <        L1254 LESS   No

I say unexpectedly, because U< and < in fig-Forth are defined much later, and U< is not a primitive, it is a combination of '-' (subtraction) and 0<. That said, the motivation to make it a primitive is sound, because U< in fig-Forth is quite frankly broken. You can see this for instance in X-Forth, which uses the fig-Forth definition:

X-FORTH 1.1b 030105/cs
0 65535 U< .
 0 OK

whereas Coin-Op Forth, which has a similar implementation for U< as the Dealer Demo,

fig-FORTH  1.4V
0 65535 U< .
 1  oK

The problem with defining U< with ": U< - 0< ;" is that when the difference is more than $7FFF, 0< is going to give the wrong answer, as it expresses a signed comparison. So it makes sense to make U< a primitive to avoid having to write a complicated implementation in Forth itself (as APX Forth did, which is probably 20x slower, and consumes more space to implement to boot).

10CE: 82 55 BC  L1246   .BYTE $82,'U',$BC
10D1: BC 10             .WORD L619
10D3: D5 10     ULESS   .WORD *+2
10D5: B5 02             LDA 2,X
10D7: D5 00             CMP 0,X
10D9: B5 03             LDA 3,X
10DB: F5 01             SBC 1,X
10DD: B0 07             BCS ULESS1
10DF: 98                TYA
10E0: 48                PHA
10E1: A9 01             LDA #1
10E3: 4C DC 0F          JMP BINARY
10E6: 98        ULESS1  TYA
10E7: 48                PHA
10E8: 4C DC 0F          JMP BINARY

The implementation of LESS is also different, but not exactly better. Here's the fig-Forth implementation:

0A1F: 21 0A     LESS    .WORD *+2
0A21: 38                SEC
0A22: B5 02             LDA 2,X
0A24: F5 00             SBC 0,X
0A26: B5 03             LDA 3,X
0A28: F5 01             SBC 1,X
0A2A: 94 03             STY 3,X
0A2C: 50 02             BVC L1258
0A2E: 49 80             EOR #$80
0A30: 10 01     L1258   BPL L1260
0A32: C8                INY
0A33: 94 02     L1260   STY 2,X
0A35: 4C EE 03          JMP POP

Now the Dealer Demo version:

10EF: F1 10     LESS    .WORD *+2
10F1: B5 02             LDA 2,X
10F3: D5 00             CMP 0,X
10F5: B5 03             LDA 3,X
10F7: F5 01             SBC 1,X
10F9: 50 02             BVC L1258
10FB: 49 80             EOR #$80
10FD: 10 07     L1258   BPL L1260
10FF: 98                TYA
1100: 48                PHA
1101: A9 01             LDA #1
1103: 4C DC 0F          JMP BINARY
1106: 98        L1260   TYA
1107: 48                PHA
1108: 4C DC 0F          JMP BINARY

The fig-Forth version frankly has a simpler/faster way of putting the result (1 or 0) into the top of the stack. The Dealer Demo version uses the trick of using CMP instead of SBC thus obviating the need to call SEC, but uses the same mechanism as ULESS to put the result on the stack. I think the fig-Forth version is the better code overall, and the same trick for setting the result could be applied to U< as well. But both work, and that's the most important part. An excellent discussion of various approaches to signed and unsigned compare can be found at http://www.6502.org/tutorials/compare_beyond.html. Section 4.3 in particular discusses the technique used here.

The next dozen words or so exactly match the implementation in the fig-Forth listing, so they don't merit much detailed discussion. They implement some arithmetic (+, -, D+, D-), some stack primitives (OVER, DROP, SWAP, DUP), some read/write primitives (@, C@, !, C!) and a couple of miscellaneous commands (+! and TOGGLE).

-def  WORD     NFA   PFA    same as fig-Forth?
110B  +        L632  PLUS   Yes
1123  D+       L649  DPLUS  Yes
1146  -        L670  MINUS  Yes
115E  D-       L685  DMINU  Yes
1177  OVER     L700  OVER   Yes
1188  DROP     L711  DROP   Yes
1191  SWAP     L718  SWAP   Yes
11AA  DUP      L733  DUP    Yes
11BA  +!       L744  PSTOR  Yes
11D7  TOGGLE   L762  TOGGL  Yes
11EB  @        L773  AT     Yes
11FF  C@       L787  CAT    Yes
120F  !        L798  STORE  Yes
1226  C!       L813  CSTOR  Yes

In our next post we'll hit colon definitions, CONSTANTs and VARIABLEs, which will encourage us to make some small enhancements to our tooling to accelerate our reverse engineering. Stay tuned.

dealerdemo.lst

0 Comments


Recommended Comments

There are no comments to display.

Guest
Add a comment...

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