00 C0 20 FD AE A0 00 99 5B 00 C8 20 73 00 90 F7 99 5B 00 A2 0B CA 98 88 30 09
B9 5B 00 29 0F 95 5B 10 F2 95 5B CA 10 FB A0 20 A2 76 18 B5 E6 90 02 09 10 4A
95 E6 E8 10 F4 A2 03 76 69 CA 10 FB 88 F0 11 A2 09 B5 5C C9 08 30 04 E9 03 95
5C CA 10 F3 30 D6 A2 03 B5 69 95 57 CA 10 F9 A9 01 85 FB A2 03 A9 00 95 FB CA
D0 FB A2 03 B5 FB 95 22 95 26 CA 10 F7 A9 00 A2 03 95 69 CA 10 FB A0 20 A2 02
46 25 76 22 CA 10 FB 90 0C A2 7C 18 B5 AA 75 ED 95 ED E8 10 F7 A2 7D 06 26 36
AA E8 10 FB 88 10 DD A2 0B A9 00 95 5A CA D0 FB A0 20 A2 09 B5 5C C9 05 30 04
69 02 95 5C CA 10 F3 06 69 A2 FD 36 6D E8 D0 FB A2 09 B5 5C 2A C9 10 29 0F 95
5C CA 10 F4 88 D0 D7 E8 B5 5B F0 FB 09 30 99 5B 00 C8 E8 E0 0B F0 04 B5 5B 90
F1 88 B9 5B 00 C9 30 F0 F8 A2 7C 18 B5 DB E9 00 95 DB E8 10 F7 90 14 88 30 05
B9 5B 00 D0 EA A2 7C F6 7F D0 03 E8 10 F9 4C 68 C0 B9 5B 00 4C D2 FF
Demo online , penggunaan: disys49152,n
manan
input 0-diindeks.
Solusi yang dimaksudkan: (beda)
B9 5B 00 29 0F 95 5B 10 F2 95 5B CA 10 FB A0 20 A2 76 18 B5 E6 90 02 09 10 4A
-95 E6 E8 10 F4 A2 03 76 69 CA 10 FB 88 F0 11 A2 09 B5 5C C9 08 30 04 E9 03 95
+95 E6 E8 10 F4 A2 03 76 69 CA 10 FB 88 F0 11 A2 09 B5 5C C9 08 90 04 E9 03 95
5C CA 10 F3 30 D6 A2 03 B5 69 95 57 CA 10 F9 A9 01 85 FB A2 03 A9 00 95 FB CA
The 30
(opcode bmi
) diganti dengan 90
(opcode bcc
). Ini sesuai dengan bagian berikut dalam sumber assembler:
stn_subloop: lda nc_string+1,x
cmp #$8
bmi stn_nosub ; use bcc here for same result
sbc #$3
sta nc_string+1,x
Ini bekerja karena kode ini memeriksa apakah angka lebih kecil dari 8. cmp
Instruksi melakukan pengurangan untuk itu, mengatur bendera yang sesuai. Jadi, jika akumulator memegang angka lebih kecil dari 8, ini mengalir di bawah, membersihkan bendera carry, oleh karena itu instruksi cabang yang benar memang bcc
. bmi
(bercabang ketika negatif), seperti dalam kode asli, kebetulan bekerja di sini juga, karena angka yang dibandingkan cukup kecil, sehingga hasil pengurangan tersebut berakhir pada rentang negatif ($80-$ff
) ketika terjadi underflow.
Demo online
Ini adalah versi yang disempurnakan / dipadatkan dari kiriman saya sebelumnya . Di antara beberapa trik lain untuk mengurangi ukuran, itu menghilangkan kode tidak berguna yang terkandung dan memungkinkan semacam "sederhana" *) retak. Secara keseluruhan, ukurannya dikurangi sebesar 16 byte. Kali ini, akan sedikit lebih sulit untuk menemukan program yang setara dengan LD 1 :)
*) mungkin masih cukup sulit untuk ditemukan, tentu saja :)
Sekali lagi, inilah ca65
sumber assembler, untuk membantu memulai dengan kode:
NUMSIZE = 4 ; 32 bit integers ...
NUMSTRSIZE = 11 ; need up to 11 characters for 0-terminated string
.segment "ZPUSR": zeropage
v_x: .res NUMSIZE ; next number to be squared
.segment "ZPFAC": zeropage
v_n: .res NUMSIZE ; input index (0-based), counts down
nc_string: .res NUMSTRSIZE ; string buffer for numbers
.segment "ZPTMP": zeropage
mpm_arg1: .res NUMSIZE ; arg1 for multiplication
mpm_arg2: .res NUMSIZE ; arg2 for multiplication
.segment "ZPFAC2": zeropage
mpm_res: .res NUMSIZE ; numeric result (mult and str convert)
; load address for creating a C64 .PRG file:
.segment "LDADDR"
.word $c000
.code
; first read number from command argument and convert to unsigned
; integer in little-endian:
jsr $aefd
ldy #$00
rn_loop: sta nc_string,y
iny
jsr $73
bcc rn_loop
sta nc_string,y
ldx #NUMSTRSIZE
stn_copybcd: dex
tya
dey
bmi stn_fillzero
lda nc_string,y
and #$f
sta nc_string,x
bpl stn_copybcd
stn_fillzero: sta nc_string,x
dex
bpl stn_fillzero
ldy #(NUMSIZE*8)
stn_loop: ldx #($81-NUMSTRSIZE)
clc
stn_rorloop: lda nc_string+NUMSTRSIZE+$80,x
bcc stn_skipbit
ora #$10
stn_skipbit: lsr a
sta nc_string+NUMSTRSIZE+$80,x
inx
bpl stn_rorloop
ldx #(NUMSIZE-1)
stn_ror: ror mpm_res,x
dex
bpl stn_ror
dey
beq main
stn_sub: ldx #(NUMSTRSIZE-2)
stn_subloop: lda nc_string+1,x
cmp #$8
bmi stn_nosub
sbc #$3
sta nc_string+1,x
stn_nosub: dex
bpl stn_subloop
bmi stn_loop
main:
ldx #(NUMSIZE-1)
argloop: lda mpm_res,x
sta v_n,x
dex
bpl argloop
lda #$01
sta v_x
ldx #(NUMSIZE-1)
lda #$00
initxloop: sta v_x,x
dex
bne initxloop
mainloop:
; prepare arguments for multiplication:
ldx #(NUMSIZE-1)
sqrargloop: lda v_x,x
sta mpm_arg1,x
sta mpm_arg2,x
dex
bpl sqrargloop
; do multiplication:
lda #$00
ldx #(NUMSIZE-1)
mul_clearloop: sta mpm_res,x
dex
bpl mul_clearloop
ldy #(NUMSIZE*8)
mul_loop: ldx #(NUMSIZE-2)
lsr mpm_arg1+NUMSIZE-1
mul_rorloop: ror mpm_arg1,x
dex
bpl mul_rorloop
bcc mul_noadd
ldx #($80-NUMSIZE)
clc
mul_addloop: lda mpm_arg2+NUMSIZE+$80,x
adc mpm_res+NUMSIZE+$80,x
sta mpm_res+NUMSIZE+$80,x
inx
bpl mul_addloop
mul_noadd: ldx #($81-NUMSIZE)
asl mpm_arg2
mul_rolloop: rol mpm_arg2+NUMSIZE+$80,x
inx
bpl mul_rolloop
dey
bpl mul_loop
; convert result to string:
ldx #NUMSTRSIZE
lda #$0
nts_fillzero: sta nc_string-1,x
dex
bne nts_fillzero
ldy #(NUMSIZE*8)
nts_bcdloop: ldx #(NUMSTRSIZE-2)
nts_addloop: lda nc_string+1,x
cmp #$5
bmi nts_noadd
adc #$2
sta nc_string+1,x
nts_noadd: dex
bpl nts_addloop
asl mpm_res
ldx #($ff-NUMSIZE+2)
nts_rol: rol mpm_res+NUMSIZE,x ; + $100 w/o zp wraparound
inx
bne nts_rol
ldx #(NUMSTRSIZE-2)
nts_rolloop: lda nc_string+1,x
rol a
cmp #$10
and #$f
sta nc_string+1,x
nts_rolnext: dex
bpl nts_rolloop
dey
bne nts_bcdloop
nts_scan: inx
lda nc_string,x
beq nts_scan
nts_copydigits: ora #$30
sta nc_string,y
iny
inx
cpx #(NUMSTRSIZE)
beq strip0loop
lda nc_string,x
bcc nts_copydigits
; search for first non-0 character from the end of the string:
strip0loop: dey
lda nc_string,y
cmp #$30
beq strip0loop
; decrement n for each digit:
founddigit:
ldx #($80-NUMSIZE)
clc
decnloop: lda v_n+NUMSIZE+$80,x
sbc #$00
sta v_n+NUMSIZE+$80,x
inx
bpl decnloop
bcc foundresult
dey
bmi next_x
lda nc_string,y
bne founddigit
; increment x to calculate next square number:
next_x:
ldx #($80-NUMSIZE)
incxloop: inc v_x+NUMSIZE-$80,x
bne incxdone
inx
bpl incxloop
incxdone: jmp mainloop
foundresult: lda nc_string,y
jmp $ffd2
... dan inilah skrip tautan untuk ld65
:
MEMORY {
LDADDR: start = $bffe, size = 2;
CODE: start = $c000, size = $1000;
ZPTMP: start = $0022, size = $0008;
ZPFAC: start = $0057, size = $000f;
ZPFAC2: start = $0069, size = $0004;
ZPUSR: start = $00fb, size = $0004;
}
SEGMENTS {
LDADDR: load = LDADDR;
CODE: load = CODE;
ZPTMP: load = ZPTMP, type = zp;
ZPFAC: load = ZPFAC, type = zp;
ZPFAC2: load = ZPFAC2, type = zp;
ZPUSR: load = ZPUSR, type = zp;
}