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)*256

2) 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 4096

Razlog: 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.)

Zaključak

Množenje i deljenje u asembleru na C64 zahtevaju kreativan pristup: sabiranje, pomeranja i rotacije. Upravo u tome je draž rada „blizu metala“. Kada je potrebno, programeri su kombinovali BASIC i mašinski kod radi jednostavnije implementacije u nekomercijalnim programima.

Ostavite komentar

Vaša adresa e-pošte neće biti objavljena. Neophodna polja su označena *

Scroll to Top