CAKE 2: Množenje i deljenje u asembleru (6510) uz primere
Množenje i deljenje u asembleru (6510) uz primere
Dobrodošli u nove cake! Danas prelazimo kroz dva naizgled „jednostavna“ zadatka koja na 6510 procesoru (C64) zahtevaju malo trikova:
množenje i deljenje bez posebnih hardverskih instrukcija. Korišćenjem sabiranja, pomeranja (shift) i rotiranja (rotate) bitova,
dobijamo precizne rezultate i razumemo kako mašina „razmišlja“.
1) Množenje (bez hardverske instrukcije)
Želimo da pomnožimo dva osmobitna broja i dobijemo rezultat (osmobitni ili šesnaestobitni — zavisno od slučaja).
Primer: 12 × 10 = 120. Pošto 6510 nema instrukciju za množenje, koristićemo sabiranje, pomeranje i rotiranje.
Primer binarnog postupka
12 × 10 → 1100 × 1010
1100 × 1010 =
0 × 1100 0000 0000 = 12 × 0 (bez rotacije)
1 × 1100 (rotacija ulevo) 0001 1000 = 12 × 1, rotacija 1 ul.
0 × 1100 (rotacija ulevo) 0000 0000 = 12 × 0, rotacija 2 ul.
1 × 1100 (rotacija ulevo) 0110 0000 = 12 × 1, rotacija 3 ul.
-----------------------------------------
Rezultat 0111 1000 = 120
Asemblerski listing (množenje)
; Adresa i inicijalizacija
*= $1000
lda #10 ; vrednost množioca
sta $fb ; smeštamo u $FB
lda #12 ; vrednost množenika
sta $fc ; smeštamo u $FC
lda #0 ; isprazni akumulator
ldx #8 ; obraditi svih 8 bita množioca
lsr $fb ; shift desno množioca, nulti bit ide u C-bit
opet ; petlja za svih 8 bita
bcc nedodaj ; ako C=0, ne sabiramo
clc ; pre sabiranja brisanje C-bit
adc $fc ; A = A + množenik
nedodaj
ror a ; rotiraj akumulator (viši bajt rezultata)
ror $fb ; rotiraj množioca
dex ; X = X - 1
bne opet ; ponavljaj dok X != 0
sta $fc ; viši bajt rezultata u $FC
rts
Nakon startovanja, rezultat množenja (ako je 16-bitni) nalazi se kao:
niži bajt u $FB/251 i viši bajt u $FC/252.
Za prikaz rezultata u BASIC-u:
PRINT PEEK(251)+PEEK(252)*2562) Deljenje (binarno oduzimanjem)
Želimo podeliti dva osmobitna broja i prikazati rezultat. Primer: 100 / 5 = 20.
Deljenje radimo slično kao na papiru, ali u binarnoj reprezentaciji i uz pomoć
pomeranja/oduzimanja.
Primer binarnog postupka
100 / 5 = 0110 0100 / 0000 0101 = 0001 0100 (20)
0 1. bit (7) / 0
01 2. bit (6) / 0
011 3. bit (5) / 0
0110
- 0101 4. bit (4) / 1
0001
00010 5. bit (3) / 0
000101
- 000101 6. bit (2) / 1
0 7. bit (1) / 0
0 8. bit (0) / 0
Asemblerski listing (deljenje)
; Adresa i inicijalizacija
*= $1000
lda #55 ; deljenik (primer)
sta $fb ; u $FB (tu će biti i krajnji rezultat)
lda #0
sta $fc ; privremena "kesa" za bitove
lda #5 ; delilac
sta $fd ; u $FD
ldx #8 ; 8 bita u bajtu
opet ; petlja kroz svih 8 bita
asl $fb ; shift levo deljenika
rol $fc ; bit koji "ispada" ide u C, pa u $FC
sec ; za oduzimanje setujemo C
lda $fc
sbc $fd ; pokušaj oduzimanja delioca
bcc preskoci ; ako C=0, oduzimanje nije uspelo
sta $fc ; ažuriraj privremenu vrednost
inc $fb ; +1 na rezultat (broji uspešne oduz.)
preskoci
dex
bne opet
rts
Po završetku, rezultat deljenja je u $FB/251. Za prikaz rezultata u BASIC-u:
PRINT PEEK(251)Važna napomena (Turbo Assembler)
Ako koristite Turbo Assembler i vraćate se u BASIC nakon prevođenja, obavezno:
SYS 64738
SYS 4096Razlog: Turbo Assembler koristi neke vektore/rutine koje BASIC koristi drugačije. Prvim pozivom resetujete sistem, drugim pokrećete vaš program od $1000 (4096), čiji su rezultati posle resetovanja izbrisani.
Za razmišljanje: BASIC mini-zadatak
10 PRINT "(SHIFT+CLR/HOME)"
20 DIM A(39)
30 FOR I=1 TO 32
40 INPUT "UNESI BROJ";M
50 IF M<1 OR M>39 THEN PRINT "POGRESNO":GOTO 40
60 IF A(M)<>0 THEN PRINT "VEC POSTOJI":GOTO 40
70 A(M)=M
80 NEXT I
85 PRINT:PRINT
90 FOR I=1 TO 39
100 IF A(I)=0 THEN PRINT I;
110 NEXT I
Šta mislite da ovaj program radi? (Nagoveštaj: Marfijev zakon.)

