Das ganze mal in 6510-Assembler für den C64. Die Begrenzung des Dividenten auf 127 Ziffern ist ein bisschen willkürlich, weil das eigentlich problemlos ohne grosse Code-Änderung auch mit bis zu 255 Ziffern gehen würde. Die Begrenzung des Divisors auf 4 Ziffern ist in der Begrenzung auf einen 16-Bit-Wert begründet, die ich wiederrum gewählt habe weil das BASIC-ROM praktischerweise eine Ausgaberoutine für 16-Bit-Werte hat die zur Ausgabe von Zeilennummern vom BASIC verwendet wird.
Code: Alles auswählen
;--------------------------------------
; Division of large integer numbers.
; Divident limit: 127 digits.
; Divisor limit: 4 digits.
; Assembler: 64tass
;--------------------------------------
divisor=$9e
remainder=$a5
tmp=$a7
divident_index=$02
quotient_index=$a9
test_data_ptr=$b0
print=$ab1e
print_word=$bdcd
chrout=$ffd2
;--------------------------------------
*=$0801
.word (+), 2019
.text $9e, format("%d", main), 0
+ .word 0
;--------------------------------------
main
lda #<test_data
sta test_data_ptr
lda #>test_data
sta test_data_ptr+1
_loop
; set divisor
ldy #0
lda (test_data_ptr),y
sta divisor
iny
lda (test_data_ptr),y
sta divisor+1
; if divisor = 0 then exit
ora divisor
beq _exit
; set divident
iny
- lda (test_data_ptr),y
sta divident-2,y
beq +
iny
bne -
+
; advance test_data_ptr
tya
sec
adc test_data_ptr
sta test_data_ptr
bcc +
inc test_data_ptr+1
+
jsr div
jsr print_result
jmp _loop
_exit
rts
;--------------------------------------
; In: divident, divisor, quotient, remainder
print_result
lda #<divident
ldy #>divident
jsr print
lda #":"
jsr chrout
ldx divisor
lda divisor+1
jsr print_word
lda #"="
jsr chrout
; TODO Skip leading zeroes.
lda #<quotient
ldy #>quotient
jsr print
lda #<txt_before_remainder
ldy #>txt_before_remainder
jsr print
ldx remainder
lda remainder+1
jsr print_word
lda #<txt_after_remainder
ldy #>txt_after_remainder
jmp print
;--------------------------------------
; In: divident, divisor
; Out: quotient, remainder
div
lda #0
sta divident_index
sta quotient_index
sta remainder
sta remainder+1
_loop
ldy divident_index
ldx divident,y
beq _exit
asl remainder ; remainder *= 10
rol remainder+1
lda remainder
sta tmp
lda remainder+1
sta tmp+1
asl remainder
rol remainder+1
asl remainder
rol remainder+1
clc
lda remainder
adc tmp
sta remainder
lda remainder+1
adc tmp+1
sta remainder+1
txa ; Add divident digit
sec
sbc #"0"
clc
adc remainder
sta remainder
bcc +
inc remainder+1
+
jsr small_div
tya
ora #"0"
ldy quotient_index
sta quotient,y
inc quotient_index
inc divident_index
bne _loop
_exit
lda #0
ldy quotient_index
bne +
lda #"0"
sta quotient,y
iny
lda #0
+
sta quotient,y
rts
;--------------------------------------
; In: remainder, divisor
; Out: Y = quotient, remainder
small_div
ldy #0
- sec
lda remainder
sbc divisor
tax
lda remainder+1
sbc divisor+1
bcc +
stx remainder
sta remainder+1
iny
bne -
+ rts
;--------------------------------------
txt_before_remainder
.text " (", 0
txt_after_remainder
.text ")", 13, 0
; Alternating divisor and 0-terminated
; divident string.
; End marked by 0 word.
test_data
.word 4
.text "500", 0
.word 37
.text "1260257", 0
.word 11
.text "26", 0
; Test the limits.
.word 9999
.fill 127, "9"
.byte 0
.word 0
;--------------------------------------
.align $100
quotient
.fill 128
divident
.fill 128