Preteceni mimo rozsah prece nevadi. Nevadi to ani pro zaporna cisla. Pokud ma byt "bignum" 16 bitove tak 16 bitove zustane.
Ptas se me jakou rutinu pouzivam na prevod TXT->BIGNUM kdyz jsem psal ze presne tohle je neco co asi stoji za to dodelat do slov a kvuli tomu resim ze nasobeni 10 se da rozepsat jako 2*(2*2+1), takze je to duvod zjistit zda jde udelat bitovy posun s prictenim puvodni hodnoty v bignum jako serii kroku, kde se cte jeden bajt za druhym, bez toho ze bych delal kopii toho bignum bokem.
Ve zkratce... nemam TXT->BIGNUM?
??? --> ??? --> ??? --> ???
Aha takze zacnu resit nasobeni trema... .)
Proste jsem si nebyl jisty zda tam neco nepretika. Ale zbytecne jsem se bal, nakonec je to jednoducha zalezitost kdy si to muzes predstavit misto
x = (x << 1) + x
jako
x *= 3
x = x + x + x + prechozi_preteceni
3*255 = 10 1111 1101
a kdybych pricetl predchozi carry tak je max 10 1111 1111 (= maximalni preteceni zustava konstantni)
A tohle plati i pro nasobeni 5.
5*255 = 100 1111 1011
K te rutine se snazim teprve dopracovat. Presneji cilem je ted _10MUL. A to je vic jak posun a pricteni. Jen to vlastne nemusi vadit, pokud nebudu mit nedostatek registru az by to bylo neefektivni delat v jednom kroku najednou.
Delam jen navrhy rutin pro _3PMUL a zrovna ted pro _5MUL.
A ani jsem je netestoval.
Kód:
dworkin@dw-A15:~/repositories/M4_FORTH/M4$ ../check_word.sh '_5PMUL(1)'
ld A,[HL] ; 1:7 5p8mul ( p8 -- p8 ) aligned [p8] *= 5
add A, A ; 1:4 5p8mul 2x
add A, A ; 1:4 5p8mul 4x
add A,[HL] ; 1:7 5p8mul 5x
ld [HL],A ; 1:7 5p8mul
; seconds: 1 ;[ 5:29]
dworkin@dw-A15:~/repositories/M4_FORTH/M4$ ../check_word.sh '_5PMUL(2)'
push DE ; 1:11 5p16mul ( p16 -- p16 ) aligned [p16] *= 5
ld E,[HL] ; 1:7 5p16mul
ld C, E ; 1:4 5p16mul
inc L ; 1:4 5p16mul
ld D,[HL] ; 1:7 5p16mul
ld B, D ; 1:4 5p16mul
ex DE, HL ; 1:4 5p16mul
add HL, HL ; 1:11 5p16mul 2x
add HL, HL ; 1:11 5p16mul 4x
add HL, BC ; 1:11 5p16mul 5x
ex DE, HL ; 1:4 5p16mul
ld [HL],D ; 1:7 5p16mul
dec L ; 1:4 5p16mul
ld [HL],E ; 1:7 5p16mul
pop DE ; 1:10 5p16mul
; seconds: 1 ;[15:106]
dworkin@dw-A15:~/repositories/M4_FORTH/M4$ ../check_word.sh '_5PMUL(3)'
push DE ; 1:11 5p24mul ( p24 -- p24 ) aligned [p24] *= 5
ld E,[HL] ; 1:7 5p24mul
ld C, E ; 1:4 5p24mul
inc L ; 1:4 5p24mul
ld D,[HL] ; 1:7 5p24mul
ld B, D ; 1:4 5p24mul
inc L ; 1:4 5p24mul
ld A,[HL] ; 1:7 5p24mul
ex DE, HL ; 1:4 5p24mul
add HL, HL ; 1:11 5p24mul
adc A, A ; 1:4 5p24mul 2x
add HL, HL ; 1:11 5p24mul
adc A, A ; 1:4 5p24mul 4x
add HL, BC ; 1:11 5p24mul
adc A,[HL] ; 1:7 5p24mul 5x
ex DE, HL ; 1:4 5p24mul
ld [HL],A ; 1:7 5p24mul
dec L ; 1:4 5p24mul
ld [HL],D ; 1:7 5p24mul
dec L ; 1:4 5p24mul
ld [HL],E ; 1:7 5p24mul
pop DE ; 1:10 5p24mul
; seconds: 0 ;[22:143]
dworkin@dw-A15:~/repositories/M4_FORTH/M4$ ../check_word.sh '_5PMUL(4)'
push HL ; 1:11 5p32mul ( p32 -- p32 ) aligned [p32] *= 5
push DE ; 1:11 5p32mul
ld BC, 0x0400 ; 3:10 5p32mul C = 0
ld D, C ; 1:4 5p32mul
ld A,[HL] ; 1:7 5p32mul 1x
add A, A ; 1:4 5p32mul 2x
ld E, C ; 1:4 5p32mul E = 0
rl E ; 2:8 5p32mul E = carry = 0..1
add A, A ; 1:4 5p32mul 4x
rl E ; 2:8 5p32mul E = carry = 0..3
add A,[HL] ; 1:7 5p32mul 5x
jr nc, $+3 ; 2:7/12 5p32mul
inc E ; 1:4 5p32mul E = carry = 0..4
add A, D ; 1:4 5p32mul + previous carry
ld [HL],A ; 1:7 5p32mul
ld A, E ; 1:4 5p32mul
adc A, C ; 1:4 5p32mul + carry
ld D, A ; 1:4 5p32mul D = carry = 0..5
inc L ; 1:4 5p32mul index++
djnz $-18 ; 2:8/13 5p32mul
pop DE ; 1:10 5p32mul
pop HL ; 1:10 5p32mul
; seconds: 0 ;[28:144]
Takze me spoilerujes hotove reseni
Coz me asi usetri praci.
PS: Aha ukazujes pouze variantu pro 16 bit a ja se snazim to mit 8..8*256 bit (pravdepodobne to nebude inline jako tyhle subrutiny, ale kdo vi... zda to vubec nekdy bude) a to jeste kdyz to lezi v pameti a ty si budes drzet jen pointer na retezec a pointer na bignum.
Jak jsem rekl, reseni jeste nemam. Pokud bych to ted nesesmolil rovnou pomoci FORTH slov, protoze moznosti na to uz ted existuji. Jen to nebude tak odladene jako asm.
PPS: A ani to nevypada po rychlem skrolovani ze bych mel USTRING nebo ISTRING prevod do UINT nebo INT. On je to pro FORTH totiz nesmysl, tohle resi parser. I kdyz mam pocit ze jsem cisla od uzivatele uz nekde nacital, jen nevim zda i viceciferne a zda jsem to resil ctenim po znaku nebo to bylo jedno slovo... Chamurabi by to mel mit!
Kód:
: input ( a_message len_message -- u )
type cr
begin
s\" " ( -- astr ulen )
over swap ( astr ulen -- astr astr ulen )
accept ( astr astr ulen -- astr uload )
s>number? ( astr uload -- d bool )
.\" \20\0\n"
0= while ( d bool -- d )
2drop ( d -- )
.\" \20\3[Please re-enter a valid number.]\n"
repeat
d>s ( d -- s )
;
a preklada me to jako STR_TO_DNUM
Kód:
dworkin@dw-A15:~/repositories/M4_FORTH/M4$ ../check_word.sh 'STR_TO_DNUM'
call STR2D ; 3:17 str>dnum ( a1_str ulen1 -- d a2_str ulen2 )
;#==============================================================================
;# Ignores all initial characters with a value less than '-', including '+' and commas.
;# An even number of '-' characters are converted to '+'
;# Number stored as a string to an signed 16-bit number.
;# It also returns the unused rest of the string.
;# ( ret a1_str ulen1 -- d2 a2_str ulen2 )
;# s" 87654321+123" str>d ( 87654321 s"+123" )
;# s" 0000087654321+123" str>d ( 87654321 s"+123" )
;# s" 87654321+123" str>d ( 87654321 s"+123" )
;# s" 0000087654321+123" str>d ( 87654321 s"+123" )
;# s" , 87654321+123" str>d ( 87654321 s"+123" )
;# s" , 0000087654321+123" str>d ( 87654321 s"+123" )
;# s" ++87654321+123" str>d ( 87654321 s"+123" )
;# s" ++0000087654321+123" str>d ( 87654321 s"+123" )
;# s" --87654321+123" str>d ( 87654321 s"+123" )
;# s" --0000087654321+123" str>d ( 87654321 s"+123" )
;# s" -87654321+123" str>d ( -87654321 s"+123" )
;# s" -0000087654321+123" str>d ( -87654321 s"+123" )
;# In: [SP] = ret, DE = a1_str, HL = ulen1
;# Out: [SP] = x, DE = a2_str, HL = ulen2
STR2DNEG: ; str>d
push BC ; 1:11 str>d
push BC ; 1:11 str>d
call STR2UD ; 3:17 str>d ( ret 0. a1_str ulen1 -- ret ud a2_str ulen2 )
exx ; 1:4 str>d negate_32
pop BC ; 1:10 str>d negate_32 BC = lo16
xor A ; 1:4 str>d negate_32
sub C ; 1:4 str>d negate_32
ld C, A ; 1:4 str>d negate_32
ld A, 0x00 ; 2:7 str>d negate_32
sbc A, B ; 1:4 str>d negate_32
ld B, A ; 1:4 str>d negate_32
pop DE ; 1:10 str>d negate_32 DE = hi16
ld A, 0x00 ; 2:7 str>d negate_32
sbc A, E ; 1:4 str>d negate_32
ld E, A ; 1:4 str>d negate_32
sbc A, D ; 1:4 str>d negate_32
sub E ; 1:4 str>d negate_32
ld D, A ; 1:4 str>d negate_32
pop AF ; 1:10 str>d negate_32 ret
push DE ; 1:11 str>d negate_32 -hi16
push BC ; 1:11 str>d negate_32 -lo16
push AF ; 1:11 str>d negate_32 ret
exx ; 1:4 str>d negate_32
ret ; 1:10 str>d
STR2D: ; str>d ( x1 ret a1_str ulen1 )
ld BC, 0x0000 ; 3:10 str>d
jr STR2D3 ; 2:12 str>d
STR2D1: ; str>d
inc C ; 1:4 str>d invert zero bit
STR2D2: ; str>d
inc DE ; 1:6 str>d str++
dec HL ; 1:6 str>d ulen
STR2D3: ; str>d
ld A, L ; 1:4 str>d
or H ; 1:4 str>d
jr z, STR2D4 ; 2:7/12 str>d
ld A,[DE] ; 1:7 str>d
cp '-' ; 2:7 str>d
jr z, STR2D1 ; 2:7/12 str>d
jr c, STR2D2 ; 2:7/12 str>d
STR2D4: ; str>d
rr C ; 2:8 str>d
ld C, B ; 1:4 str>d
jr c, STR2DNEG ; 2:7/12 str>d
pop AF ; 1:10 str>d ret
push BC ; 1:11 str>d
push BC ; 1:11 str>d
push AF ; 1:11 str>d ( 0. ret a1_str ulen1 )
;... fall to str>ud
;#==============================================================================
;# Adds a number stored as a string to an unsigned 32-bit number.
;# It also returns the unused rest of the string.
;# ( ud1 ret a1_str ulen1 -- ud2 a2_str ulen2 )
;# 12345. s" 67890+123" >number ( 1234567890. s"+123" )
;# 0. s" 1234567890+123" >number ( 1234567890. s"+123" )
;# In: [SP+4] = hi16, [SP+2] = lo16, [SP] = ret, DE = a1_str, HL = ulen1
;# Out: [SP+2] = hi16, [SP] = lo16, DE = a2_str, HL = ulen2
STR2UD: ; str>ud
pop BC ; 1:10 str>ud ret
exx ; 1:4 str>ud
pop DE ; 1:10 str>ud lo16
ex [SP],HL ; 1:19 str>ud hi16, [SP] = R.A.S.
ex DE, HL ; 1:4 str>ud HL = lo16, DE = hi16
exx ; 1:4 str>ud
jr STR2UD2 ; 2:7/12 str>ud
STR2UD1: ; str>ud
inc DE ; 1:6 str>ud str++
dec HL ; 1:6 str>ud ulen--
exx ; 1:4 str>ud
add HL, HL ; 1:11 str>ud
rl E ; 2:8 str>ud
rl D ; 2:8 str>ud 2x
ld C, L ; 1:4 str>ud
ld B, H ; 1:4 str>ud
push DE ; 1:11 str>ud
add HL, HL ; 1:11 str>ud
rl E ; 2:8 str>ud
rl D ; 2:8 str>ud 4x
add HL, HL ; 1:11 str>ud
rl E ; 2:8 str>ud
rl D ; 2:8 str>ud 8x
add HL, BC ; 1:11 str>ud
pop BC ; 1:10 str>ud
ex DE, HL ; 1:4 str>ud
adc HL, BC ; 2:15 str>ud 10x
ex DE, HL ; 1:4 str>ud
add A, L ; 1:4 str>ud If L contains the value
ld L, A ; 1:4 str>ud 25-->250, 51-->254, 76-->248, 102-->252,
jr nc, $+6 ; 2:7/12 str>ud 153-->250, 179-->254, 204-->248, 230-->252
inc H ; 1:4 str>ud so there is a risk that it could exceed 255
jr nz, $+3 ; 2:7/12 str>ud 6553*10-->0xfffa,13107*10-->0xfffe,19660*10-->0xfff8,26214*10-->0xfffc,
inc DE ; 1:6 str>ud 39321*10-->0xfffa,45875*10-->0xfffe,52428*10-->0xfff8,58982*10-->0xfffc
exx ; 1:4 str>ud
STR2UD2: ; str>ud
ld A, L ; 1:4 str>ud
or H ; 1:4 str>ud
jr z, STR2UD3 ; 2:7/12 str>ud
ld A,[DE] ; 1:7 str>ud
sub '0' ; 2:7 str>ud
cp 10 ; 2:7 str>ud
jr c, STR2UD1 ; 2:7/12 str>ud
STR2UD3: ; str>ud
exx ; 1:4 str>ud
ex DE, HL ; 1:4 str>ud HL = hi16, DE = lo16
ex [SP],HL ; 1:19 str>ud HL = R.A.S., [SP] = hi16
push DE ; 1:11 str>ud lo16
exx ; 1:4 str>ud
push BC ; 1:11 str>ud ret
ret ; 1:10 str>ud
; seconds: 1 ;[121:694]
A kdyz existuje DNUM tak bude existovat i STR_TO_NUM
Kód:
dworkin@dw-A15:~/repositories/M4_FORTH/M4$ ../check_word.sh 'STR_TO_NUM'
call STR2S ; 3:17 str>num ( a1_str ulen1 -- x a2_str ulen2 )
;#==============================================================================
;# Ignores all initial characters with a value less than '-', including '+' and commas.
;# An even number of '-' characters are converted to '+'
;# Number stored as a string to an signed 16-bit number.
;# It also returns the unused rest of the string.
;# ( ret a1_str ulen1 -- x2 a2_str ulen2 )
;# s" 4321+123" str>s ( 4321 s"+123" )
;# s" 000004321+123" str>s ( 4321 s"+123" )
;# s" 4321+123" str>s ( 4321 s"+123" )
;# s" 000004321+123" str>s ( 4321 s"+123" )
;# s" , 4321+123" str>s ( 4321 s"+123" )
;# s" , 000004321+123" str>s ( 4321 s"+123" )
;# s" ++4321+123" str>s ( 4321 s"+123" )
;# s" ++000004321+123" str>s ( 4321 s"+123" )
;# s" --4321+123" str>s ( 4321 s"+123" )
;# s" --000004321+123" str>s ( 4321 s"+123" )
;# s" -4321+123" str>s ( -4321 s"+123" )
;# s" -000004321+123" str>s ( -4321 s"+123" )
;# In: [SP] = ret, DE = a1_str, HL = ulen1
;# Out: [SP] = x, DE = a2_str, HL = ulen2
STR2SNEG: ; str>s
push BC ; 1:11 str>s
call STR2U ; 3:17 str>s ( ret 0 a1_str ulen1 -- ret u a2_str ulen2 )
pop BC ; 1:10 str>s
xor A ; 1:4 str>s negate
sub C ; 1:4 str>s negate
ld C, A ; 1:4 str>s negate
sbc A, B ; 1:4 str>s negate
sub C ; 1:4 str>s negate
ld B, A ; 1:4 str>s negate
pop AF ; 1:10 str>s ret
push BC ; 1:11 str>s
push AF ; 1:11 str>s ( -u ret a2_str ulen2 )
ret ; 1:10 str>s
STR2S: ; str>s ( x1 ret a1_str ulen1 )
ld BC, 0x0000 ; 3:10 str>s
jr STR2S3 ; 2:12 str>s
STR2S1: ; str>s
inc C ; 1:4 str>s invert zero bit
STR2S2: ; str>s
inc DE ; 1:6 str>s str++
dec HL ; 1:6 str>s ulen
STR2S3: ; str>s
ld A, L ; 1:4 str>s
or H ; 1:4 str>s
jr z, STR2S4 ; 2:7/12 str>s
ld A,[DE] ; 1:7 str>s
cp '-' ; 2:7 str>s
jr z, STR2S1 ; 2:7/12 str>s
jr c, STR2S2 ; 2:7/12 str>s
STR2S4: ; str>s
rr C ; 2:8 str>s
ld C, B ; 1:4 str>s
jr c, STR2SNEG ; 2:7/12 str>s
pop AF ; 1:10 str>s ret
push BC ; 1:11 str>s
push AF ; 1:11 str>s
;... fall to str>u
;#==============================================================================
;# Adds a number stored as a string to an unsigned 16-bit number.
;# It also returns the unused rest of the string.
;# ( u1 ret a1_str ulen1 -- u2 a2_str ulen2 )
;# 54 s" 321+123" rot s>d 2swap >number 2swap d>s -rot ( 54321 s"+123" )
;# 0 s" 54321+123" rot s>d 2swap >number 2swap d>s -rot ( 54321 s"+123" )
;# In: [SP+2] = u1, [SP] = ret, DE = a1_str, HL = ulen1
;# Out: [SP] = u2, DE = a2_str, HL = ulen2
STR2U: ; str>u ( u1 ret a1_str ulen1 )
pop BC ; 1:10 str>u ret
exx ; 1:4 str>u
ex [SP],HL ; 1:19 str>u u1
exx ; 1:4 str>u
jr STR2U2 ; 2:7/12 str>u
STR2U1: ; str>u
inc DE ; 1:6 str>u str++
dec HL ; 1:6 str>u ulen
exx ; 1:4 str>u
add HL, HL ; 1:11 str>u 2x
ld C, L ; 1:4 str>u
ld B, H ; 1:4 str>u BC = 2x
add HL, HL ; 1:11 str>u 4x
add HL, HL ; 1:11 str>u 8x
add HL, BC ; 1:11 str>u 10x
add A, L ; 1:4 str>u If L contains the value
ld L, A ; 1:4 str>u 25-->250, 51-->254, 76-->248, 102-->252,
jr nc, $+3 ; 2:7/12 str>u 153-->250, 179-->254, 204-->248, 230-->252,
inc H ; 1:4 str>u so there is a risk that it could exceed 255
exx ; 1:4 str>u
STR2U2: ; str>u
ld A, L ; 1:4 str>u
or H ; 1:4 str>u
jr z, STR2U3 ; 2:7/12 str>u
ld A,[DE] ; 1:7 str>u
sub '0' ; 2:7 str>u
cp 10 ; 2:7 str>u
jr c, STR2U1 ; 2:7/12 str>u
STR2U3: ; str>u ( ret a2_str u2 ) BC = ulen2
exx ; 1:4 str>u
ex [SP],HL ; 1:19 str>u u2
exx ; 1:4 str>u
push BC ; 1:10 str>u ret
ret ; 1:10 str>u
; seconds: 0 ;[82:478]
Takze je to rozdelene na dve pomocne rutiny, jedna co prevadi signed na unsigned a druha co nasobi mezivysledek 10 a pricita desitkovou cifru. A ta druha je ekvivalent toho co si ukazoval ty.