装配atoi头晕错误

时间:2011-01-10 13:56:53

标签: assembly

我们有一个字符串,其偏移量为di。此proc将在ax中将其转换为整数。 proc将在0-999之间正常工作。但是例如对于1000或2343或其他大于1000的数字将不起作用。问题出在哪儿 ?我很困惑。 tlen也是我定义的临时字节。

 atoi 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

2 个答案:

答案 0 :(得分:1)

那太可怕了:))

无论如何,它不起作用的直接原因是你使用8位乘法,特别是mul dlmul bl几乎不适用于1000,但10000以上也会失败。

一般建议:学会使用调试器逐步执行代码并查看出错的地方。

答案 1 :(得分:1)

问题是“mul dl”。 DL是一个8位寄存器,因此DL可以容纳的最大值是255.您可能正确地乘以100(例如“99 * 100 + 9 = 999”),然后不能乘以1000或更高。

代码需要使用更大的寄存器。代码也需要重写,以便每个字符只能执行一个MUL。

示例(NASM,未经测试):

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..

上面的代码假定一个80386或更高版本的CPU(并且以实模式或16位代码工作),并应处理高达“2 ** 32-1”(超过4)的值亿元)。

对于在您出生之前可能已经过时的80x86 CPU(80286及更早版本),您需要使用一对寄存器(例如DX:AX)而不是32位寄存器来获得相同的范围,或限制它结果小于65536并使用16位寄存器而不是32位寄存器(例如将EBX替换为BX,将EAX替换为AX等)。