RETRO KUTAK – tehnologija prošlih decenija

CAKE 2: Množenje i deljenje u asembleru (6510) uz primere

C64 – CAKE 2: praktični vodič za množenje i deljenje na procesoru 6510 (Commodore 64), bez hardverske instrukcije.
Objašnjavamo multipliciranje sabiranjem, shift/rotate pristup, binarne primere (1100×1010), kao i deljenje oduzimanjem.
Uključeni su kompletni asemblerski listinzi, BASIC komande za očitavanje rezultata (PEEK), kao i Turbo Assembler napomene
(SYS 64738, SYS 4096). Fokus: C64 asembler množenje, C64 deljenje, 6510 assembly, retro programiranje.

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.

Оставите одговор

Ваша адреса е-поште неће бити објављена. Неопходна поља су означена *