multiplikation8.asm
Aus C64-Wiki
Zur Navigation springenZur Suche springen
;#################################################################### ;# Programm: 8-Bit-Multiplikation ;# Dateiname: multiplikation8.asm ;# ;# Assembler: ACME ;# Assemblierung: acme -f cbm -o mul8.prg multiplikation8.asm ;# ;# Laden mit: LOAD"mul8.prg",8,1 ;# ;# Speicher: Belegt den Bereich $c000 bis $c032 ;# ;# Aufruf mit: jsr $c000; die beiden zu multiplizierenden ;# Werte müssen im X- und Y-Register stehen, das ;# Ergebnis wird im A-Register zurück geliefert. ;# Ein gesetztes Carry-Flag signalisiert einen ;# Fehler. ;# ;# Quelltext: * Kleinschreibung (bis auf Kommentare) ;# * nur Leerzeichen, keine Tabulatoren ;# * Labels immer in eigener Zeile ;# * Befehle zwei Zeichen eingerückt ;# * Kommentare i.d.R. nach den Befehlen ;# ;# Beschreibung: Die Routine multipliziert zwei 8-Bit-Werte ;# miteinander. Der Wertebereich ist auf 0 bis 255 ;# beschränkt; wird er überschritten, löst dies einen ;# Fehler aus. ;# ;# Zum Algorithmus: ;# ;# N. Wirth hat in seinem Buch "Compilerbau" als ;# Beispiel für die dort verwendete Sprache "PL/0" ;# (eine stark abgespeckte Variante von Pascal) ;# eine Multiplikations-Routine verwendet: ;# ;# procedure multiply; ;# var a, b; ;# begin ;# a := x; ;# b := y; ;# z := 0; ;# while b > 0 do ;# begin ;# if odd b then z := a + z; ;# a := a * 2; ;# b := b div 2 ;# end ;# end; ;# ;# Der in dem genannten Buch enthaltene Compiler ;# erzeugt aus der dieser Routine einen P-Code, ;# der als Vorlage für das nachfolgende Assembler- ;# Programm diente. ;# ;# Um sicher zu stellen, dass es bei einem Überlauf ;# (Ergebnis ist oder wird größer als 255) nicht zu ;# falschen Ergebnissen kommt, wird bei der Addition ;# und der Multiplikation (shift left) eine Fehler- ;# kontrolle über das Carry-Flag durchgeführt und die ;# Berechnung bei zu großen Werten mit einem Fehler ;# abgebrochen. ;# ;#################################################################### ; -- Startadresse -- *=$c000 ;#################################################################### ;# ;# Speicherstellen ;# ;#################################################################### !addr a = $69 ; Zeropage-Adressen des Accum#2 !addr b = $6a !addr z = $6b ;#################################################################### ;# ;# Hauptroutine ;# ;#################################################################### ; -- mul8 -- ; Die Werte im X- und Y-Register werden multipliziert ; und das Ergebnis in den Akku geschrieben; ; ein gesetztes Carry-Flag zeigt einen Fehler an ; (Ergebnis ist/wird größer als 255); in diesem Fall ; wird das Ergebnis auf 255 gesetzt. mul8 stx a sty b lda #0 sta z ; while b > 0 do - lda b beq +++ ; Abbruchbedingung b = 0 ; if odd b then z := a + z lsr bcc ++ ; b ist gerade (Bit 0 nicht gesetzt) clc ; a + z lda a adc z bcc + lda #$ff ; a + z ist größer 255 sec rts + sta z ; Ergebnis von a + z speichern ++ ; Wenn b gleich 1 ist, ist dies der letzte Durchgang ; der Schleife. Daher wird hier die Schleife vorzeitig ; verlassen, damit die Multiplikation a * 2, deren ; Ergebnis dann ohnehin verworfen würde, keinen ; Fehler mehr auslösen kann (was passieren würde, ; wenn a in diesem Moment größer als 127 wäre). lda b cmp #1 beq +++ ; Abbruchbedingung b = 1 ; a := a * 2; b := b div 2 asl a ; a * 2 bcc + lda #$ff ; a * 2 ist größer 255 sec rts + lsr b ; b div 2 jmp - +++ lda z ; Ergebnis im Akku clc ; kein Fehler aufgetreten rts