mirror of
https://github.com/Michaelangel007/apple2_russian_peasant_multiplication.git
synced 2024-12-21 14:30:06 +00:00
Assembly merlin 32 version
This commit is contained in:
parent
f45c2b1ec3
commit
1c278d95d5
346
rpm_m32.s
Normal file
346
rpm_m32.s
Normal file
@ -0,0 +1,346 @@
|
||||
; ASC
|
||||
; DFB
|
||||
;.include "ca65_fixes.inc"
|
||||
|
||||
ZERO_LEAD EQU $00
|
||||
|
||||
KEY_CR EQU $8D
|
||||
KEY_ESC EQU $9B
|
||||
KEY_0 EQU $B0 ; '0' = $30
|
||||
KEY_9 EQU $B9 ; '9' = $39
|
||||
|
||||
pDigits EQU $FA
|
||||
Carry EQU $FC
|
||||
Div EQU $FD
|
||||
|
||||
KEYBOARD EQU $C000
|
||||
KEYSTROBE EQU $C010
|
||||
|
||||
TEXT EQU $FB2F ; Init text mode and window
|
||||
HOME EQU $FC58
|
||||
RDKEY EQU $FD0C
|
||||
COUT EQU $FDED
|
||||
|
||||
__main = $2000
|
||||
|
||||
; Header for DOS 3.3 binary file; remove 2 lines for ProDOS
|
||||
DW __main
|
||||
DW __end - __main
|
||||
|
||||
; main()
|
||||
ORG __main
|
||||
|
||||
LDA #7 ; Version
|
||||
JSR TEXT ; Just in case we are in graphics mode
|
||||
JSR HOME
|
||||
JSR InitABS ; Init A,B,S
|
||||
JSR IntroH
|
||||
JSR InputA ; Input
|
||||
JSR InputB
|
||||
JSR IntroS
|
||||
|
||||
MulDigit ; Calc
|
||||
JSR IsZeroB
|
||||
BCS OutS
|
||||
|
||||
JSR IsOddB
|
||||
BCC EvenS
|
||||
JSR AddAToS
|
||||
EvenS
|
||||
JSR ShlA
|
||||
JSR ShrB
|
||||
CLC
|
||||
BCC MulDigit ; ^ (always)
|
||||
OutS
|
||||
JSR PrintS ; output
|
||||
;RTS ; NOTE: DOS3.3 BRUN bug doesn't exit, should JMP $3D0
|
||||
JMP $0000
|
||||
|
||||
InputA
|
||||
JSR IntroA
|
||||
JSR GetPtrA
|
||||
BNE GetString
|
||||
InputB
|
||||
JSR IntroB
|
||||
JSR GetPtrB
|
||||
; intentional fall int GetString
|
||||
GetString ; common entry point
|
||||
STX pDigits
|
||||
STY pDigits+1
|
||||
|
||||
LDX #0 ; digits length
|
||||
_linechar
|
||||
JSR GetDigit ; C=1 enter, C=0 digit
|
||||
BCS _linedone
|
||||
JSR COUT ; preserves A,Y
|
||||
AND #$F ; C=0 digit
|
||||
STA Buffer,X
|
||||
INX
|
||||
BPL _linechar ; or BNE for 255 digits
|
||||
BMI IntroE ; error if > 127 digits
|
||||
_linedone ; Now move digits from $200 -> DigitsA, DigitsB, etc.
|
||||
|
||||
LDY #0 ; X = src, Y = dst offset
|
||||
CPX #0 ; any digits?
|
||||
BEQ _movedone ; No digits!
|
||||
_moveline
|
||||
DEX
|
||||
LDA Buffer,X
|
||||
STA (pDigits),Y ; digit[y] = char & 0xF
|
||||
INY
|
||||
CPX #0
|
||||
BNE _moveline ; ^ max 256 digits
|
||||
_movedone
|
||||
BEQ PrintCR ; v (always)
|
||||
|
||||
GetDigit
|
||||
; LDA KEYBOARD
|
||||
; BPL GetDigit
|
||||
; STA KEYSTROBE
|
||||
JSR RDKEY
|
||||
CMP #KEY_CR
|
||||
BEQ _eol
|
||||
CMP #KEY_ESC
|
||||
BEQ _esc
|
||||
CMP #KEY_0
|
||||
BCC GetDigit
|
||||
CMP #KEY_9+1
|
||||
BCS GetDigit
|
||||
RTS
|
||||
_eol SEC ; C=1 enter
|
||||
RTS
|
||||
_esc ; Unwind stack of InputA/B
|
||||
PLA
|
||||
PLA
|
||||
RTS ; Return to who originally called main()
|
||||
|
||||
GetPtrA
|
||||
LDX #<DigitsA ; lo byte
|
||||
LDY #>DigitsA ; hi byte
|
||||
RTS
|
||||
GetPtrB
|
||||
LDX #<DigitsB
|
||||
LDY #>DigitsB
|
||||
RTS
|
||||
GetPtrS
|
||||
LDX #<DigitsS
|
||||
LDY #>DigitsS
|
||||
RTS
|
||||
|
||||
InitABS
|
||||
LDA #$00
|
||||
TAX
|
||||
_zero
|
||||
STA DigitsA,X
|
||||
STA DigitsB,X
|
||||
STA DigitsS,X
|
||||
INX
|
||||
BNE _zero ; zero digits[0..$FF]
|
||||
RTS
|
||||
|
||||
|
||||
IntroA LDY #OffsetA
|
||||
BNE _intro
|
||||
IntroB LDY #OffsetB
|
||||
BNE _intro
|
||||
IntroS LDY #OffsetS
|
||||
BNE _intro
|
||||
IntroE LDY #OffsetE
|
||||
BNE _intro
|
||||
IntroH
|
||||
LDY #OffsetH
|
||||
_intro
|
||||
LDA _text,Y
|
||||
BEQ _outro ; asciiz
|
||||
JSR COUT
|
||||
INY
|
||||
BNE _intro
|
||||
_outro
|
||||
RTS
|
||||
PrintCR
|
||||
LDA #KEY_CR
|
||||
JMP COUT
|
||||
|
||||
; ________________________________________________________________________
|
||||
; Pseudo BCD - one byte per digit
|
||||
; ________________________________________________________________________
|
||||
|
||||
; ========================================
|
||||
PrintA
|
||||
JSR GetPtrA
|
||||
BNE _print
|
||||
PrintB
|
||||
JSR GetPtrB
|
||||
BNE _print
|
||||
PrintS
|
||||
JSR GetPtrS
|
||||
_print
|
||||
STX _bcd+1
|
||||
STY _bcd+2
|
||||
LDX #ZERO_LEAD ; Default to leading zero ($0)
|
||||
LDY #$FF ; start at digits[255]
|
||||
_bcd
|
||||
LDA $FFFF,Y ; NOTE: Self-Modified by _print
|
||||
BNE _digit ; digits[i] == 0 && leadingzero
|
||||
CPX #ZERO_LEAD ; X != 0
|
||||
BEQ _skip
|
||||
_digit
|
||||
CLC
|
||||
ADC #KEY_0 ; 0 -> $B0 .. 9 -> $B9
|
||||
TAX ; If digit printed stop checking for leading zero
|
||||
JSR COUT
|
||||
_skip
|
||||
DEY ;
|
||||
CPY #$FF ; digits[255] ?
|
||||
BNE _bcd ; ^
|
||||
|
||||
; Bug fix: If no digits were printed then number must be zero
|
||||
LDA #0 ; print '0'
|
||||
TAY ; no length
|
||||
CPX #ZERO_LEAD
|
||||
BEQ _digit
|
||||
BNE PrintCR ; ^ (always) move to next line when done
|
||||
|
||||
; ========================================
|
||||
AddAToS
|
||||
LDY #0
|
||||
CLC
|
||||
_add
|
||||
LDA DigitsS,Y
|
||||
ADC DigitsA,Y
|
||||
CMP #$A ; Base=10, C = (a+s+carry) >= 10
|
||||
BCC _overflow
|
||||
SBC #$A ; C=1, A = A - 9 - C
|
||||
_overflow
|
||||
STA DigitsS,Y
|
||||
INY
|
||||
BNE _add
|
||||
RTS
|
||||
|
||||
; ========================================
|
||||
IsOddB
|
||||
LDY #0
|
||||
LDA DigitsB,Y
|
||||
AND #1
|
||||
BEQ _not_zero ; Even -> C=0
|
||||
BNE _is_zero ; Odd _> C=1
|
||||
|
||||
; ========================================
|
||||
IsZeroB
|
||||
LDY #0
|
||||
_is_0
|
||||
LDA DigitsB,Y
|
||||
BNE _not_zero
|
||||
INY
|
||||
BNE _is_0
|
||||
_is_zero
|
||||
SEC
|
||||
RTS
|
||||
_not_zero
|
||||
CLC
|
||||
RTS
|
||||
|
||||
; ========================================
|
||||
ShlA
|
||||
LDY #0
|
||||
CLC
|
||||
_shl
|
||||
LDA DigitsA,Y
|
||||
TAX
|
||||
LDA Mul2Digit,X
|
||||
ADC #0
|
||||
STA DigitsA,Y
|
||||
LDA Mul2Carry,X
|
||||
ROR
|
||||
INY
|
||||
BNE _shl
|
||||
RTS
|
||||
|
||||
; ========================================
|
||||
ShrB
|
||||
LDY #$FF ; start at digits[255]
|
||||
LDX #0 ; digits processed
|
||||
STX Carry ; $00 .. 9*2 = $18
|
||||
_shr
|
||||
CLC ;
|
||||
LDA DigitsB,Y ; sum = digit[i] + carry
|
||||
ADC Carry ; A=0000_00xy C=0/1
|
||||
ROR ; A=c000_000x, C=y
|
||||
AND #$F ; A=0000_000x
|
||||
STA DigitsB,Y ; digit[i] = (sum / 2)
|
||||
LDA #0 ;
|
||||
BCC _shr_next ; C=0 -> Carry = 0
|
||||
LDA #10 ; C=1 -> Carry = 10 (base)
|
||||
_shr_next
|
||||
STA Carry ; carry = (sum & 1) ? BASE : 0
|
||||
DEY
|
||||
INX ; we need to compare y=$FF without disturbing carry
|
||||
BNE _shr ; max 256 digits -- solution, use X reg :-)
|
||||
RTS
|
||||
|
||||
Mul2Digit ; Digit
|
||||
DFB 0 ; 0*2 = 0 0
|
||||
DFB 2 ; 1*2 = 0 2
|
||||
DFB 4 ; 2*2 = 0 4
|
||||
DFB 6 ; 3*2 = 0 6
|
||||
DFB 8 ; 4*2 = 0 8
|
||||
DFB 0 ; 5*2 = 1 0
|
||||
DFB 2 ; 6*2 = 1 2
|
||||
DFB 4 ; 7*2 = 1 4
|
||||
DFB 6 ; 8*2 = 1 6
|
||||
DFB 8 ; 9*2 = 1 8
|
||||
Mul2Carry ; Carry
|
||||
DFB 0 ; 0*2 = 0 0
|
||||
DFB 0 ; 1*2 = 0 2
|
||||
DFB 0 ; 2*2 = 0 4
|
||||
DFB 0 ; 3*2 = 0 6
|
||||
DFB 0 ; 4*2 = 0 8
|
||||
DFB 1 ; 5*2 = 1 0
|
||||
DFB 1 ; 6*2 = 1 2
|
||||
DFB 1 ; 7*2 = 1 4
|
||||
DFB 1 ; 8*2 = 1 6
|
||||
DFB 1 ; 9*2 = 1 8
|
||||
|
||||
_text
|
||||
TextH ; Header
|
||||
ASC "RUSSIAN PEASANT MULTIPLICATION"
|
||||
DFB KEY_CR
|
||||
DFB KEY_CR
|
||||
DFB 0
|
||||
TextA
|
||||
ASC "INPUT A"
|
||||
DFB KEY_CR
|
||||
ASC "?"
|
||||
DFB 0
|
||||
TextB
|
||||
ASC "INPUT B"
|
||||
DFB KEY_CR
|
||||
ASC "?"
|
||||
DFB 0
|
||||
TextE
|
||||
DFB KEY_CR
|
||||
ASC "WARNING"
|
||||
ASC ": MORE THAN 127 CHARS"
|
||||
DFB KEY_CR
|
||||
DFB 0
|
||||
TextS
|
||||
ASC "= "
|
||||
DFB 0
|
||||
|
||||
OffsetH EQU TextH - _text
|
||||
OffsetA EQU TextA - _text
|
||||
OffsetB EQU TextB - _text
|
||||
OffsetE EQU TextE - _text
|
||||
OffsetS EQU TextS - _text
|
||||
|
||||
__end
|
||||
|
||||
; Pad until end of page, these globals are not stored on disk
|
||||
DUM *
|
||||
DS \
|
||||
DigitsA DS 256 ; stupid assembler can't use variable 'a'
|
||||
DigitsB DS 256
|
||||
DigitsS DS 256
|
||||
Buffer DS 256
|
||||
DEND
|
||||
|
Loading…
Reference in New Issue
Block a user