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
在线演示,用法:sys49152,n
此处n
为0索引输入。
预期解决方案:(差异)
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
的30
(操作码bmi
)被替换为90
(操作码bcc
)。这对应于汇编器源代码中的以下部分:
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
之所以有效,是因为该代码检查数字是否小于8。该cmp
指令为此执行减法运算,并相应地设置标志。因此,如果累加器保持的数字小于8,则该下溢,清除进位标志,因此正确的转移指令的确是bcc
。bmi
(在负数时分支)在原始代码中也一样,因为比较的数字足够小,所以$80-$ff
当发生下溢时,相减的结果最终在负数范围()中。
在线演示
这是我以前提交的文章的改进/精简版本。在减少大小的其他技巧中,它删除了所包含的无用代码,并允许一种“简单” *)破解。总而言之,大小减小了16个字节。这次,要找到与LD 1等效的程序应该有点困难:)
*)当然,可能还有很多工作要做:)
再次,这是ca65
汇编程序源,以帮助您开始使用代码:
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
...这是以下链接器的脚本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;
}