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
Démo en ligne , utilisation:sys49152,n
oùn
est l'entrée indexée 0.
Solution envisagée: (diff)
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
L' 30
opcode bmi
est remplacé par l' 90
opcode bcc
. Cela correspond à la partie suivante dans la source de l'assembleur:
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
Cela fonctionne car ce code vérifie si un nombre est inférieur à 8. L' cmp
instruction effectue une soustraction pour cela, définissant les indicateurs en conséquence. Donc, si l'accumulateur contient un nombre inférieur à 8, cela sous-estime, effaçant le drapeau de report, donc la bonne instruction de branchement est en effet bcc
. bmi
(ramification lorsqu'elle est négative), comme dans le code d'origine, fonctionne également ici, car les nombres comparés sont suffisamment petits, de sorte que le résultat de la soustraction se retrouve dans la plage négative ($80-$ff
) lorsqu'un débordement se produit.
Démo en ligne
Il s'agit d'une version améliorée / compactée de ma soumission précédente . Parmi d'autres astuces pour réduire la taille, il supprime le code inutile qui était contenu et permettait une sorte de "simple" *) crack. Dans l'ensemble, la taille est réduite de 16 octets. Cette fois, il devrait être un peu plus difficile de trouver le programme équivalent avec LD 1 :)
*) probablement encore pas mal de travail à trouver, bien sûr :)
Encore une fois, voici la ca65
source de l' assembleur, pour vous aider à démarrer avec le code:
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
... et voici le script de l'éditeur de liens pour 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;
}