@Hyperion: Der Prozessor kann ja nur addieren, subtrahieren, und Bits verschieben. Daraus muss man sich das selber basteln. Simpelste, aber vielleicht nicht eleganteste Variante für ``a % b`` ist so lange `b` von `a` abziehen wie ``b > a`` gilt. Das was dann übrig bleibt wäre der Rest der Division. Wenn man mit zählt wie oft man das gemacht hat, bekommt man auch den ganzzahligen Anteil der Division heraus.
Trotz fehlender Eleganz wäre das bei dieser Aufgabe aber IMHO sogar im Bereich des Tolerierbaren. Das wären maximal 14 Schleifendurchläufe für 100 und 7.
Ansonsten muss man sich eine effizientere Division basteln, wo auch der Rest bei heraus fällt. Ist bei Byte/Byte auch nur eine Handvoll Befehle in einer Schleife.
Ich habe sowohl das Modulo-7 als auch das Teilen durch 10 für die Ausgabe umgangen. Ersteres, in dem ich einfach parallel einen Zähler laufen lasse um jeden 7. Durchlauf der Schleife zu erkennen. Und für die Umwandlung in eine Zeichenkette bemühe ich Routinen im BASIC-ROM:
Code: Alles auswählen
!to "test.prg", cbm
chrout = $ffd2
strout = $ab1e
ldf_u8 = $b3a2
f2str = $bddd
i = $fa
j = $fb
* = $c000
lda #1 ; i = 1
sta i
lda #7 ; j = 7
sta j
loop
dec j ; every 7th iteration -> print asterisk
bne .not_div_7
lda #7
sta j
bne print_asterisk
.not_div_7
ldy i ; FAC = i
jsr ldf_u8
jsr f2str ; $0100... = STR(FAC) + 0x00; A/Y = $0100
lda #"7" ; compare digits with "7"
cmp $0101
beq print_asterisk
cmp $0102
beq print_asterisk
tya ; print number (A/Y = $0101)
jsr strout
jmp print_space
print_asterisk
lda #"*"
jsr chrout
print_space
lda #" "
jsr chrout
inc i ; i++
ldy i
cpy #101 ; already i == 101?
bne loop
lda #13 ; print newline
jmp chrout
Und wo ich schon dabei war, hier das Problem 2:
Code: Alles auswählen
!to "test.prg", cbm
intout = $bdcd
strout = $ab1e
ldf = $bba2
stf = $bbd4
ldf_u8 = $b3a2
fltmul = $ba28
fltout = $aabc
i = $fa
f_one = $bfe8
* = $c000
ldx #4 ; n = 1.0
- lda f_one,x
sta n,x
dex
bpl -
lda #0 ; i = 0
sta i
loop
lda #0 ; print i
ldx i
jsr intout
lda #<txt ; print "! ="
ldy #>txt
jsr strout
lda #<n ; FAC = n
ldy #>n
jsr ldf
jsr fltout ; print FAC + newline
ldy i ; FAC = i + 1
iny
jsr ldf_u8
lda #<n ; FAC *= n
ldy #>n
jsr fltmul
ldx #<n ; n = FAC
ldy #>n
jsr stf
inc i ; i++
lda i ; loop finished?
cmp #11
bne loop
rts
txt: !pet "! =", 0
n: * = * + 5
Da mache ich auch Gebrauch von den Gleitpunktzahl-Routinen im BASIC-ROM um die Multiplikation und die Umwandlung in Dezimaldarstellung nicht selbst implementieren zu müssen. Da kann man nun natürlich streiten ob das geschummelt ist.
Ach ja: Quelltext ist für den ACME-(Cross-)Assembler.