traslation
- From: "¬a\\/b" <al@xxx>
- Date: Sun, 28 Jan 2007 08:22:58 +0100
this is the traslation of sscan_m function posted some time ago
with my macro assembly language
For who belive in c language: why don't you rewrite this in C and
see if will be better?
section _DATA public use32 class=DATA
global _sscan_m
align 16, db 0
dieci_1 dt 1.0 , 10.0 , 100.0, 1000.0, 10000.0, 100000.0
dt 1.0e6 , 1.0e7, 1.0e8, 1.0e9 , 1.0e10 , 1.0e11, 1.0e12,
1.0e13
dt 1.0e14, 1.0e15
dieci_16 dt 1.0 , 1.0e16 , 1.0e32 , 1.0e48 , 1.0e64 ,
1.0e80 , 1.0e96, 1.0e112
dt 1.0e128, 1.0e144, 1.0e160, 1.0e176, 1.0e192,
1.0e208, 1.0e224, 1.0e240
dieci_256 dt 1.0 , 1.0e256 , 1.0e512 , 1.0e768 , 1.0e1024,
1.0e1280, 1.0e1536, 1.0e1792
dt 1.0e2048, 1.0e2304, 1.0e2560, 1.0e2816, 1.0e3072,
1.0e3328, 1.0e3584, 1.0e3840
dt 1.0e4096, 1.0e4352, 1.0e4608, 1.0e4864 /* 20=0..19
align 16, db 0 /* +InF
piu_oo dd 0, 0x80000000, 0x7FFF, 0
align 16, db 0 /* -InF
meno_oo dd 0, 0x80000000, 0xffff, 0
align 16, db 0
dbl_min dq -1.7976931348E+308
align 16, db 0
dbl_max dq 1.7976931348E+308
align 16, db 0
dbl_min_ep dq 2.2250738585E-308
align 16, db 0
dbl_min_em dq -2.2250738585E-308
dieci dd 10, 0
cw_data dw 0000001101111111b
dw 0
dd 0, 0, 0, 0, 0
/* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
tab dd 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x36ff /* 0
dd 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
/* 10
dd 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
/* 20
dd 0xff, 0xff,0x37ff,0x1ff, 0xff,
0xff,0x33ff,0x35ff,0xff,0x34ff /* 30
dd 0x31ff,0xff, 0xff, 0xff, 0xff, 0x3ff, 0xff, 0xff, 0x0, 0x1
/* 40
dd 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xff, 0xff
/* 50
dd 0xff, 0xff, 0xff, 0xff, 0xff, 0xa, 0xb, 0xc, 0xd, 0xe
/* 60
dd 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
/* 70
dd 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22
/* 80
dd 0x23, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa, 0xb, 0xc
/* 90
dd 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
/* 100
dd 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
/* 110
dd 0x21, 0x22, 0x23, 0xff, 0xff, 0xff, 0x2ff
/* 120
times 132 dd 0xff
section _TEXT public use32 class=CODE
/* r:k mult10<r:k>
/* ma (r:k)*10< 1 0 0 ? clearCarry: setCarry
/* 0 j, 4 i, 8 c, 12 b, 16 a, 20 Ra
_mult10:
< a, b, c, i, j
/*------------------*/
c=r; j=k; a=k; /* salva input in c:j
mul D*dieci; /* k*10
i=a; k=r; /* save result in i:k
a=c; mul D*dieci;
a+=k | jnc .m0 | ++r;
..m0:
r!=0 #.mfineset;
r=a; k=i;
r&0x80000000|jnz .mfineset
/* qui perde un bit per il segno
clc; #.mfine
..mfineset:
r=c; k=j;
stc;
..mfine:
a, b, c, i, jret
/* input signed int a; output 10^a in st0
/* utilizza due posizioni dello fpu-stack
/* non inizializza niente; rounding mode per troncamento
/* settato all'esterno
_fpow10i_m:
< a, b, c
a< -4931 ?#.ze
a> 4931 ?#.oo
#.c0
.ze: fldz; ##.fine
.oo: fld T*piu_oo; ##.fine
.c0: b=0; a&0x80000000 | jz .c1 | neg a | b=1
.c1: c=a; c&=0xF; c= &[c+4*c]; c= &[2*c];/* c= c*10 serve poiche' un
FLD T[dieci_1 + c]; /* elemento occupa 10 chars
c=a; c>>= 4; c&=0xF; c= &[c+4*c]; c= &[2*c];
FLD T[dieci_16 + c];
c=a; c>>= 8; FMULP st1; /* ok poiche' c<=4931
c= &[c+4*c]; c= &[2*c]; /* e 4931>>8 == 19
FLD T[dieci_256 + c];
b<>1; FMULP st1; jnz .fine
FLD1 | FDIVRP st1
..fine:
a, b, cret
/* segno in b
/* numero nello stack del chiamante in num1:num0 numero
/* di cifre in c, ultima posizione in j
/* nel caso di errore o nessun numero stc altrimenti clc
/* converti<origine i>
/* 0 @sign, 4k, 8r, 12 i, 16 a, 20 Ra, 24 num0, 28 num1
converti:
< a, i, r, k /* i punta sempre al carattere
/* corrente della stringa
<< @sign=[s]
s-=4
#.c1 /* leva gli spazi
..c0: ++i| .c1: B*i==' ' #.c0;
D @sign=0;
B*i=='+' !#.b0 | ++i; #.c2
..b0: B*i=='-' !#.c2 | ++i; ++D @sign;
..c2: B*i>'9' #.ce
B*i<'0' #.ce /* nel caso dopo eventuale + o -
#.b1; /* c'e' un non numero => errore
..ce: r=0; k=0; a=0; c=0; b=0; j=^12; ##.cf
..b1: #.g1 /* leva gli zeri
..g0: ++i| .g1: B*i=='0' #.g0;
a=0; r=0; k=0; j=0; c=0;
..c3: al=*i /* prende parte non esponente
al<='9' !#.c4
al>='0' !#.c4
_mult10(); jc .r1
al-='0'; k+=a | jnc .b2| ++r | jno .b2
k-=a; --r; --c;
.r1: ##.c7
.b2: ++i| #.c3;
..c4: al=='.' #.a1 | ##.c9;
..a1: B[i+1]>'9'#.a2 | B[i+1]<'0'#.a2
#.a3
..a2: ##.c9; /* caso numero.?non_numero
..a3: j=i; /* caso numero.?numero
..ca: ++j; al=*j /* elimina gli zeri superflui
al>'9'#.cb;
al<'0'#.cb;
#.ca;
..cb: --j; al=*j | al=='0'#.cb /* j punta *all'ultimo numero* non zero
// i==j!#.cd; ##.c9 /* tranne caso numero.000000000
// modificata levando la linea di sopra (allora non prendeva exps)
..cd: i==j#.a0
++i; al=*i;
_mult10(); jc .a0 /* elimina i restanti decimali
al-='0'; --c; k+=a | jnc .a4; ++r | jno .a4
k-=a; --r; #.a0
.a4: #.cd;
..c7: ++c; ++i; al=*i /* caso 999etc
al<='9' !#.c8
al>='0' #.c7
..c8: al=='.' !#.c9 /* caso 999etc.etc
B[i+1]>'9'#.c9;
B[i+1]<'0'#.c9;
.a0: ++i; al=*i
al<='9' !#.c9
al>='0' #.a0
..c9: j=i; b=@sign;
..cf: s+=4
j==[s+8] !#.cc | stc | #.cz
..cc: clc /* [s+8]==i
..cz: [s+20]=k; [s+24]=r; /* nello stack la risposta
ret@signa, i, r, k
/* <j>pos <a>num+sign converti_exp<j>
converti_exp:
< b, c, r, i, k
i=j; b=0; r=0;
..c0: ++j| B*j==' ' #.c0; /* leva gli spazi
B*j=='+'!#.c1 | ++j; #.c2
..c1: B*j=='-'!#.c2 | ++j; ++b;
..c2: B*j>'9' #.ce
B*j<'0' #.ce /* nel caso dopo eventuale + o -
#.c3
..ce: j=i; a=0; ##.cf
..c3: #.c5 /* leva gli zeri
..c4: ++j| .c5: B*j=='0' #.c4;
a=0; c=0; k=0;
..c6: cl=*j
cl<='9' !#.c8
cl>='0' !#.c8
mul D*dieci;
cl-='0'; a+=c;
a>4931#.ck
++j | #.c6;
..ck: ++j; cl=*j
cl<='9' !#.c8
cl>='0' !#.c8 | #.ck
..c8: b==1!#.cf | neg a
..cf:
b, c, r, i, kret
/* st0 AsciiToSt0_m(P_string, P_address_then);
/* se [P_address_then]==[P_string] allora st0=0 e non e' preso
/* altrimenti
/* il numero e' preso. Utilizza due registri dello stack-fpu
/* CF==1 overflow CF==0 non overflow
/* per k: 0 k, 4Ra, 8P_string, 12P_address
AsciiToSt0_m:
{< k
k = s;
< b, c, r, i, j
s-=16 /* s=0num0, 4num1, 8sign, 12cw_save
fnstcw [s+12];
fldcw [cw_data]; /* resetta tutto + troncamento
/* converti scrive nello 2 dd nello stack qui allocato
i=[k+8]; converti(); jnc .a0
a=[k+8]; b=[k+12]; *b=a; fldz; ##.cx
..a0: [s+8]=b; a=0; /* caso non errore
#.c1 /* leva gli spazi
..c0: ++j| .c1: B*j==' '#.c0;
bl=B*j;
bl=='e' #.c2 /* 44.44 e -12455
bl!='E' #.c3
..c2: converti_exp(); /* in a esponente
a> 4931 ?#.ce_piu_oo
c> 4931 ?#.ce_piu_oo
a< -4931 ?#.ce_zero
..c3: a+=c
/* uPrint_m(titolo, a);
a> 4931 ?#.ce_piu_oo
a< -4931 ?#.ce_zero
#.c4
..ce_piu_oo: b=1;
D[s+8]==0!#.seielmeno |fld T*piu_oo | stc; ##.cq;
..seielmeno: fld T*meno_oo; stc; ##.cq;
..ce_zero: fldz; ##.cf;
..c4: b=0;
_fpow10i_m(); /* st = 10^a
..c5: fild Q[s]; /* st = num, 10^a
fmulp st1 /* st = num*10^a
..cf: D[s+8]==0 #.aa; FCHS;
..aa: clc
..cq: a=[k+12]; *a=j;
..cx: fldcw [s+12];
a=b;
s=&[s+16];
b, c, r, i, js = k
k;ret 8
/* eax __stdcall StrToUns(char* string, char** pos, int base)
/* eg. char buf[256]={0}, *pc; int val=StrToUns(buf, &pc, 10);
/* CF== carry flag
/* format==<spaces><+><digits> where spaces={' ', '\t'}
/* convert the number in format above in the 0 terminated
/* string "string" in the base format in a integer in the range
/* [0, 0xffffffff] that return in eax.
/* 2<=base<=36 possible digits "0123456789[A-Z][a-z]"
/* if there is not a number in the above format then
/* after the call => (string==pos and CF==1)
/* if overflow return 0xffffffff CF==1
/* if there is (or not) overflow it read all the number
/* and save in "pos" the first not digit position
/* if all is ok CF==0 if error CF==1
/* 0i, 4r, 8c, 12b, 16ra, 20string, 24pos, 28base
StrToUns:
< b, c, r, i
<< @string=[s+20], @pos=[s+24], @base=[s+28]
..in: i=@string; i==0#.ce; b^=b;
c=@base; c>36#.ce; c<=1#.ce;
#.c1;
..c0: {++i; .c1: B*i==' '#.c0; B*i==9#.c0;}
B*i=='+'!#.c2 | ++i;
..c2: bl=*i; [tab+4*b]>=c#.ce;
#.c5;
..ce: a=@pos; r=@string; *a=r; a=0; ##.ca;
..c4: {++i; .c5: B*i=='0'#.c4; }
a=0;
..c6: bl=*i; r=[tab+4*b];
r>=c#.c8
b = r;
mul c | r#.c7 /* in ci +/-oo
a+=b | jc .c7
++i; #.c6;
..c7: {++i; bl=*i; r=[tab+4*b]; r<c#.c7;}
..ci: r=1; a=0xFFFFFFFF; #.c9;
..c8: r=0;
..c9: b=@pos; *b=i;
r==0!#.ca; clc; #.cf
..ca: stc;
..cf:
ret 12@string, @posb, c, r, i
/* eax __stdcall StrToInt(char* string, char** pos, int base)
/* eg. char buf[256]={0}, *pc; int val=StrToInt(buf, &pc, 10);
/* CF== carry flag
/* format==<spaces><+|-><digits> where spaces={' ', '\t'}
/* convert the number in format above in the 0 terminated
/* string "string" in the base format in a integer in the range
/* [-2147483648, 2147483647] that return in eax.
/* 2<=base<=36 possible digits "0123456789[A-Z][a-z]"
/* if there is not a number in the above format then
/* after the call => (string==pos and CF==1)
/* if overflow for number > 0 return 2147483647 CF==1
/* if overflow for number < 0 return -2147483648 CF==1
/* if there is (or not) overflow it read all the number
/* and save in "pos" the first not digit position
/* if all is ok CF==0 if error CF==1
/* 0k, 4i, 8r, 12c, 16b, 20Ra, 24string, 28pos, 32base
StrToInt:
< b, c, r, i, k
<< @string=[s+24], @pos=[s+28], @base=[s+32]
..in: i=@string; i==0#.ce; b^=b;
c=@base; c>36#.ce; c<=1#.ce;
k=0; #.c1; /* in k il segno
..c0: {++i; .c1: B*i==' '#.c0; B*i==9#.c0;}
B*i=='+'!#.c2 | ++i; #.c3;
..c2: B*i=='-'!#.c3 | ++i; ++k;
..c3: bl=*i; [tab+4*b]>=c#.ce;
#.c5;
..ce: a=@pos; r=@string; *a=r; a=0; ##.ca;
..c4: {++i; .c5: B*i=='0'#.c4; }
a=0;
..c6: bl=*i; r=[tab+4*b];
r>=c#.c8
b = r;
mul c | r#.c7 /* in ci +/-oo
a+=b | jc .c7
++i; #.c6;
..c7: {++i; bl=*i; r=[tab+4*b]; r<c#.c7;}
..ci: r=1; a=0x7FFFFFFF; #.a0;
..c8: r=0;
a<>0x80000000; <#.a0; >#.ci;
k==1#.c9; #.ci; /* a=0x80000000
..a0: k==1!#.c9;
r==1!#.a1; ++a; #.c9;
..a1: neg a;
..c9: b=@pos; *b=i;
r==0!#.ca; clc; #.cf
..ca: stc;
..cf:
ret 12@string, @posb, c, r, i, k
/* int _sscan_m<(char** ove, char* input, char* fmt, ...)
/* k=0k, 4k, 8ra, 12@ove, 16@input, 20@fmt, 24@P0, 28P1, 32P2 etc
/* SEE < in _sscan_m<(
/* 1 2
/* fmt=<all>%<[i|d|u|f|L|*s|digits&s|p|x|c]><all>
/* 1== si scarta la stringa fino al prossimo carattere di fmt
/* 2== si prende una stringa di al massimo lunghezza "digits"
/*
/* sscan_m gets from string pointed from input values follow
/* string fmt specifications. it return eax
/* if eax > 0 then all ok and in eax there is the number of
/* converted elements [%*s not counted] (CF==0)
/* if eax <= 0 then some error occur and in -eax there is
/* the number of argumet converted [%*s not counted] (CF==1)
/* You NOTE CF is changed when a C compiler clear the stack s+=offset
/* so for use CF you have to use assembly and s=&[s+offset];
/* fmt="%i %d %u %x %p %f %L %DECIMAL_NUMBERSs %*s " [integer=32bits]
/* [%i, %d mean signed integer] [%u means unsigned integer]
/* [%x, %p mean unsigned integer in base 16 format]
/* [%f means 64 bits float (double)], [%L means 80 bits double]
/* [%DECIMAL_NUMBERSs ] mean read the string of max DECIMAL_NUMBERS
/* len, until next char fmt is found and put the result in the
/* argument
/* [%*s] mean read the string until 0 or next char fmt is found
_sscan_m:
< k, k
k = s;
< b, c, r, i, j
s-=128;
<< @ove=[k+12], @input=[k+16], @fmt=[k+20], @w=[s+8]
D[k]=0; c=&[k+24]; j=@input; i=@fmt;
j==0#.ce; i==0#.ce; b=0; D @ove==0#.ce; #.c0;
..ce: D[k]=1; ##.cf;
..c0: #.x0
..c1: {++i; .x0: al=*i; al==0#.c3; /* sviluppare caso al==0
al==' '#.c1; al==9#.c1; al==10#.c1}
..c2: #.c4
..c3: ##.cf;
..c4: al!='%'!#.ca; #.c6;
..c5: { { ++j; .c6: al=*j; al==0#.c8;
al==' '#.c5; al==9#.c5; al==10#.c5; }
#.c8;
..c7: {++i,j; .c8: al=*i; rl=*j; al==0#.c3; al==rl#.c7; }
al=='%'#.ca; al==' '#.c1;
al==9#.c1; al==10#.c1; #.x2;
..x1: {++j; .x2: rl=*j; al==rl#.c7;
rl==' '#.x1; rl==9#.x1; rl==10#.x1; }
##.ce;
}
..a0: ##.ce;
..ca: /* qui *i=='%'
D*c==0#.ce;
#.y0;
..y1: {++j; .y0: al=*j; al==' '#.y1; al==9#.y1; al==10#.y1; }
++i; al=*i; ++i;
al>'9'#.w3; al<'0'#.w3;
r=& @w; --i; StrToUns(i, r, 10); jc .a0; a==0#.a0;
i=*r; B*i!='s'#.a0; ++i; r=*c; @w=b; #.w1;
..w0: {*r=bl; ++r,j;
..w1: bl=*j; bl==0#.w2; bl==[i]#.w2; --a#.w0;}
..w2: b=@w; B*r=0; c+=4; ++b; ##.c0;
..w3: al=='u'!#.cc; r=& @w; StrToUns(j, r, 10); jnc .cb| D[k]=1;
..cb: j==[r]#.a0;
j=*r; r=*c; c+=4; *r=a; ++b; ##.c0;
..cc: al=='i'!#.ch;
..cd: r=& @w; StrToInt(j, r, 10); jnc .cg| D[k]=1;
..cg: j==[r]#.a1;
j=*r; r=*c; c+=4; *r=a; ++b; ##.c0;
..a1: ##.ce;
..ch: al=='d'#.cd;
al=='x'!#.cm;
..ci: B*j=='0'!#.a3| B[j+1]=='x'!#.a2 | j+=2; #.a3;
..a2: B[j+1]=='X'!#.a3 | j+=2;
..a3: r=& @w; StrToUns(j, r, 16); jnc .cl| D[k]=1;
..cl: j==[r]#.a1;
j=*r; r=*c; c+=4; *r=a; ++b; ##.c0;
..cm: al=='p'#.ci;
..cq: al=='f'!#.a4;
r=& @w; AsciiToSt0_m(j,r); a==1!#.m0| D[k]=1;
..m0: j==[r]!#.cr | FSTP T [s]; ##.a1;
..cr: j =*r; r=*c;
FCOM Q*dbl_min; FSTSW ax; sahf;
!<=#.h0| FSTP T [s]; FLD Q*dbl_min; #.h1;
..h0: FCOM Q*dbl_max; FSTSW ax; sahf;
!>=#.y2| FSTP T [s]; FLD Q*dbl_max;
..h1: D[k]=1; #.h2;
..a4: #.cs;
..y2: FTST; FSTSW ax; sahf; >#.y3; /* <=0
FCOM Q*dbl_min_em; FSTSW ax; sahf;
!>=#.h2; #.y4;
..y3: FCOM Q*dbl_min_ep; FSTSW ax; sahf;
!<=#.h2;
..y4: FSTP T [s]; FLDZ;
..h2: FSTP Q[r];
..h3: c+=4; ++b; ##.c0;
..cs: al=='L'!#.cu;
r=& @w; AsciiToSt0_m(j,r); a==1!#.m1| D[k]=1;
..m1: j==[r]!#.ct | FSTP T [s]; ##.a1;
..ct: j =*r; r=*c; FSTP T[r]; c+=4; ++b; ##.c0;
..cu: al=='c'!#.cv | r^=r; rl=*j; r==0!#.m2 | ##.ce;
..m2: ++j; a=*c; B*a=rl;c+=4; ++b; a^=a; ##.c0;
..cv: al=='*'!#.cz; B[i]=='s'!#.cz; ++i; #.y6;
..y5: {++j; .y6: rl=*j; rl==0#.y7; rl!=[i]#.y5;}
..y7: ##.c0; /* notare che potrebbe essere B*i==0
..cz: ##.ce;
..cf: a=@ove; *a=j; a=b;
s+=128;@ove, @input, @fmt, @w
b, c, r, i, jD[k]==1!#.xa | neg a; stc; #.xb /* CF==1 Errore
.xa: clc; /* ma la cancellazione dello stack s+=off_set
.xb: /* è un problema perchè modifica CF
s = k; /* CF handle overflow
k, kret
.
- Follow-Ups:
- Re: traslation
- From: Raye Cutsin
- Re: traslation
- Prev by Date: Re: Merge sort
- Next by Date: Re: a propose for a suppose far better sscanf in assembly
- Previous by thread: Some help translating some asm to C
- Next by thread: Re: traslation
- Index(es):
Relevant Pages
|