We have a string which its offset is in di. This proc will convert it to integer in ax. The proc will work good for 0-999. but for example for 1000 or 2343 or other numbers greater Than 1000 will not work. where is the problem ? I have confused. also tlen is temp byte that i have defined.
at开发者_高级运维oi proc far
mov cl,len
mov ch,0
mov ah,0
start:
dec cl
jcxz addlastdigit
mov tlen,cl;save cl
mov al,1
mov bl,10
getMultiplier:
mul bl
Loop getMultiplier
mov cl,tlen ; retrive cl
mov dl,byte ptr[di]
sub dl,30h
mul dl
add num,ax
inc di
jmp start
addlastdigit:
mov ax,num
mov dl,byte ptr[di]
sub dl,30h
mov dh,0
add ax,dx
Ret
atoi endp
The problem is "mul dl". DL is an 8-bit register, so the maximum value DL can hold is 255. You probably multiply by 100 correctly (e.g. "99*100+9 = 999), then fail to multiply by 1000 or higher.
The code needs to use larger registers. The code also needs to be rewritten so that it only does one MUL per character.
Example (NASM, untested):
atioi:
xor eax,eax
.nextChar:
movzx ebx,byte [di]
inc di
sub bl,'0'
jb .invalidChar
cmp bl,9
ja .invalidChar
lea eax,[eax*4+eax]
sub ecx,1
lea eax,[eax*2+ebx]
jne .nextChar
ret
.invalidChar:
; Not sure what you're planning to do with error handling..
The code above assumes an 80386 or later CPU (and will work in real mode or 16-bit code), and should handle values up to "2**32-1" (over 4 billion) properly.
For 80x86 CPUs that were probably obsolete before you were born (80286 and older) you'd need to use a pair of registers (e.g. DX:AX) instead of 32-bit registers to get the same range, or limit it to results that are less than 65536 and use 16-bit registers instead of the 32-bit registers (e.g. replace EBX with BX, EAX with AX, etc).
That's quite horrible :)
Anyway, the immediate reason why it doesn't work is that you are using 8 bit multiplies, in particular, the mul dl
. The mul bl
barely happens to work for 1000, but will also fail for 10000 and above.
General advice: learn to use a debugger to step through your code and see where it goes wrong.
精彩评论