A2 03 B5 FB 95 26 CA 10 F9 88 D0 01 60 A5 26 85 61 A5 27 85 62 A5 FB 85 63 A5
FC 85 64 A9 20 85 6F D0 36 18 A5 6D 65 65 85 28 A5 6E 65 66 85 29 A5 4B 85 26
A5 4C 85 27 50 CF 38 A5 6D E5 65 85 4B A5 6E E5 66 85 4C A5 28 85 61 A5 29 85
62 A5 FB 85 63 A5 FC 85 64 06 6F A9 00 85 65 85 66 A2 10 46 62 66 61 90 0D A5
63 18 65 65 85 65 A5 64 65 66 85 66 06 63 26 64 CA 10 E6 A9 FF 24 6F 70 B9 30
02 F0 9E A5 65 85 6D A5 66 85 6E 24 6F 30 14 A5 28 85 61 A5 29 85 62 A5 FD 85
63 A5 FE 85 64 06 6F D0 B4 A5 26 85 61 A5 27 85 62 A5 FD 85 63 A5 FE 85 64 06
6F B0 A0
- Geliştirilmiş "spagetti" yapısına sahip -12 bayt
- -2 bayt üs geçmek için kaydı değiştirir, böylece ilk kopya döngüsünde sıfır adresleme modunu kullanabiliriz
Bu konumdan bağımsız bir koddur, sadece RAM'de bir yere koyun ve bir jsr
talimatla çağırın .
Rutin (karmaşık) tabanı, $fb/$fc
(gerçek) ve $fd/$fe
(hayali) içinde iki 16 bit işaretli tam sayı (2'nin tamamlayıcısı, küçük-endian) ve Y
kayıtta işaretsiz bir 8 bit tam sayı olarak alır .
Sonuç $26/$27
(gerçek) ve $28/$29
(hayali) olarak döndürülür .
açıklama
Bu, 6502 CPU'da hala ilginç bir zorluktur, çünkü çarpma için bile talimat yoktur. Yaklaşım basittir, karmaşık bir çarpımı uygular ve üssün gerektirdiği sıklıkta uygular. Golf, alt rutinlerden kaçınarak yapılır, bunun yerine bir çeşit "dal spagetti" yaratılır, böylece birden çok kez ihtiyaç duyulan basit bir 16 bit çarpma kodu mümkün olan en düşük ek yük ile yeniden kullanılır. Yorum yapılan sökme:
.cexp:
A2 03 LDX #$03 ; copy argument ...
.copyloop:
B5 FB LDA $FB,X
95 26 STA $26,X
CA DEX
10 F9 BPL .copyloop ; ... to result
.exploop:
88 DEY ; decrement exponent
D0 01 BNE .mult ; zero reached -> done
60 RTS
.mult: ; multiply (complex) result by argument
A5 26 LDA $26 ; prepare to multiply real components
85 61 STA $61 ; (a*c)
A5 27 LDA $27
85 62 STA $62
A5 FB LDA $FB
85 63 STA $63
A5 FC LDA $FC
85 64 STA $64
A9 20 LDA #$20 ; marker for where to continue
85 6F STA $6F
D0 36 BNE .mult16 ; branch to 16bit multiplication
.mult5:
18 CLC ; calculate sum (a*d) + (b*c)
A5 6D LDA $6D
65 65 ADC $65
85 28 STA $28 ; and store to imaginary component of result
A5 6E LDA $6E
65 66 ADC $66
85 29 STA $29
A5 4B LDA $4B ; load temporary result (a*c) - (b*d)
85 26 STA $26 ; and store to real component of result
A5 4C LDA $4C
85 27 STA $27
50 CF BVC .exploop ; next exponentiation step
.mult3:
38 SEC ; calculate difference (a*c) - (b*d)
A5 6D LDA $6D
E5 65 SBC $65
85 4B STA $4B ; and store to temporary location
A5 6E LDA $6E
E5 66 SBC $66
85 4C STA $4C
A5 28 LDA $28 ; prepare to multiply real component of result
85 61 STA $61 ; with imaginary component of argument
A5 29 LDA $29 ; (a*d)
85 62 STA $62
A5 FB LDA $FB
85 63 STA $63
A5 FC LDA $FC
85 64 STA $64
06 6F ASL $6F ; advance "continue marker"
.mult16:
A9 00 LDA #$00 ; initialize 16bit multiplication
85 65 STA $65 ; result with 0
85 66 STA $66
A2 10 LDX #$10 ; bit counter (16)
.m16_loop:
46 62 LSR $62 ; shift arg1 right
66 61 ROR $61
90 0D BCC .m16_noadd ; no carry -> nothing to add
A5 63 LDA $63 ; add arg2 ...
18 CLC
65 65 ADC $65
85 65 STA $65
A5 64 LDA $64
65 66 ADC $66
85 66 STA $66 ; ... to result
.m16_noadd:
06 63 ASL $63 ; shift arg2 left
26 64 ROL $64
CA DEX ; decrement number of bits to go
10 E6 BPL .m16_loop
A9 FF LDA #$FF ; check marker for where to continue
24 6F BIT $6F
70 B9 BVS .mult3
30 02 BMI .saveres ; have to save result to temp in 2 cases
F0 9E BEQ .mult5
.saveres:
A5 65 LDA $65 ; save result to temporary
85 6D STA $6D
A5 66 LDA $66
85 6E STA $6E
24 6F BIT $6F ; check "continue marker" again
30 14 BMI .mult4
.mult2:
A5 28 LDA $28 ; prepare to multiply imaginary components
85 61 STA $61 ; (b*d)
A5 29 LDA $29
85 62 STA $62
A5 FD LDA $FD
85 63 STA $63
A5 FE LDA $FE
85 64 STA $64
06 6F ASL $6F ; advance "continue marker"
D0 B4 BNE .mult16 ; branch to 16bit multiplication
.mult4:
A5 26 LDA $26 ; prepare to multiply imaginary component of
85 61 STA $61 ; result with real component of argument
A5 27 LDA $27 ; (b*c)
85 62 STA $62
A5 FD LDA $FD
85 63 STA $63
A5 FE LDA $FE
85 64 STA $64
06 6F ASL $6F ; advance "continue marker"
B0 A0 BCS .mult16 ; branch to 16bit multiplication
Kullanan örnek program (C64, ca65- syntax içindeki montaj kaynağı ):
.import cexp
CEXP_A = $fb
CEXP_AL = $fb
CEXP_AH = $fc
CEXP_B = $fd
CEXP_BL = $fd
CEXP_BH = $fe
CEXP_RA = $26
CEXP_RAL = $26
CEXP_RAH = $27
CEXP_RB = $28
CEXP_RBL = $28
CEXP_RBH = $29
.segment "LDADDR"
.word $c000
.segment "MAIN"
jsr $aefd ; consume comma
jsr $ad8a ; evaluate number
jsr $b1aa ; convert to 16bit int
sty CEXP_AL ; store as first argument
sta CEXP_AH
jsr $aefd ; ...
jsr $ad8a
jsr $b1aa
sty CEXP_BL ; store as second argument
sta CEXP_BH
jsr $b79b ; read 8bit unsigned into X
txa ; and transfer
tay ; to Y
jsr cexp ; call our function
lda CEXP_RAH ; read result (real part)
ldy CEXP_RAL
jsr numout ; output
ldx CEXP_RBH ; read result (imaginary part)
bmi noplus
lda #'+' ; output a `+` if it's not negative
jsr $ffd2
noplus: txa
ldy CEXP_RBL
jsr numout ; output (imaginary part)
lda #'i'
jsr $ffd2 ; output `i`
lda #$0d ; and newline
jmp $ffd2
numout:
jsr $b391 ; convert to floating point
jsr $bddd ; format floating point as string
ldy #$01
numout_loop: lda $ff,y ; output loop
bne numout_print ; until 0 terminator found
rts
numout_print: cmp #' ' ; skip space characters in output
beq numout_next
jsr $ffd2
numout_next: iny
bne numout_loop
Kullanımı: sys49152,[a],[b],[c]
Örneğin sys49152,5,2,2
(Çıktı: 21+20i
)