Mã máy 6502 (C64), LD = 1, an toàn
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
Bản demo trực tuyến , cách sử dụng:sys49152,n
đâun
là đầu vào 0 chỉ mục.
Giải pháp dự định: (khác)
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
Các 30
(opcode bmi
) được thay thế bằng 90
(opcode bcc
). Điều này tương ứng với phần sau trong nguồn trình biên dịch chương trình:
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
Nó hoạt động vì mã này kiểm tra xem một số có nhỏ hơn 8. Lệnh cmp
thực hiện phép trừ cho điều đó hay không, đặt các cờ tương ứng. Vì vậy, nếu bộ tích lũy giữ một số nhỏ hơn 8, thì phần này sẽ tràn ra, xóa cờ mang theo, do đó, hướng dẫn chi nhánh chính xác là thực sự bcc
. bmi
(phân nhánh khi âm), như trong mã gốc, cũng xảy ra hoạt động ở đây, bởi vì các số được so sánh là đủ nhỏ, do đó, kết quả của phép trừ kết thúc trong phạm vi âm ( $80-$ff
) khi xảy ra dòng chảy ngầm.
Bản demo trực tuyến
Đây là phiên bản cải tiến / nén của lần gửi trước của tôi . Trong số một số thủ thuật khác để giảm kích thước, nó loại bỏ mã vô dụng được chứa và cho phép một loại vết nứt "đơn giản" *). Tất cả trong tất cả, kích thước được giảm 16 byte. Lần này, sẽ khó hơn một chút để tìm chương trình tương đương với LD 1 :)
*) có lẽ vẫn còn một số công việc cần tìm, tất nhiên :)
Một lần nữa, đây là ca65
nguồn trình biên dịch, để giúp bắt đầu với mã:
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
... và đây là tập lệnh liên kết cho 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;
}