Dealer Demo, part 6: Less is More
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.