Assembly 在程序集中将字符串解析为整数

Assembly 在程序集中将字符串解析为整数,assembly,x86,type-conversion,masm,Assembly,X86,Type Conversion,Masm,我的代码应该将字符串格式解析为int,但它将f.e.0更改为658688,我不知道如何处理它。 这里的lodsd命令正确吗 toparse DB 128 dup(?) mov toparse, "0" atoi proc uses esi edx inputBuff:DWORD mov esi, inputBuff xor edx, edx .Repeat lodsd .Break .if !eax imul edx, edx, 10 sub eax, "0" add edx, eax .

我的代码应该将字符串格式解析为int,但它将f.e.0更改为658688,我不知道如何处理它。 这里的lodsd命令正确吗

toparse DB 128 dup(?)
mov toparse, "0"

  atoi proc uses esi edx inputBuff:DWORD
mov esi, inputBuff
xor edx, edx
.Repeat
lodsd
.Break .if !eax
imul edx, edx, 10
sub eax, "0"
add edx, eax
.Until 0
mov EAX, EDX
ret
  atoi endp

它返回658688

您需要
调用带有ascii内存偏移量的atoi进程,或者
推送
调用atoi之前的偏移量。现在
esi
将只包含
inputbuff
中已有的随机值

我已经修改了proc,以便它能够成功地处理完整的字符串

toparse db "12345678",0

;mov toparse,"0" ; Max is 4 bytes so define string above

push offset toparse ; |
call atoi           ; - or: invoke atoi,offset toparse  

...

atoi proc uses esi inputBuff:DWORD ; Generally only need to preserve esi, edi and ebx
mov esi,inputBuff
xor edx,edx
xor eax,eax         ; Clear register
.Repeat
lodsb               ; Get one byte
.Break .if !eax
imul edx,edx,10     ; Multiply total by 10
sub eax,"0"         ; Subtract 48
add edx,eax         ; Add result to the total
.Until 0
mov eax,edx         ; Will result in 00BC614E (hex 12345678)
ret
atoi endp

... <如果字符串编码为UTF-32或其他4字节编码,则代码>lodsd
可能是正确的。它可能不像mov toparse那样是“0”。你签入调试器了吗,发生了什么事?很难读懂你的源代码,因为它不是纯汇编,我认为有一些宏或其他东西。。。或者这些是“待办事项”评论,这些不是评论。代码使用MASM的高级汇编语法。我猜它们就像宏,但它们是内置在汇编程序中的。
lodsd
是错误的。它加载一个双字(DWORD),但您的字符显然是字节大小的,因为您已经使用
DB
(Declare byte)声明了一个字符串数组。您可能需要
lodsb
。十六进制的结果值658688是
0x0A0D00
,因此好消息是您的代码可以正常工作(低字节是
0
,正如预期的那样)。我打赌其他两个字节来自您的输入例程:您结束它的输入。因此,如果要调整循环,请在本例程中测试输入字符串的结尾,或者检查每个字符以查看它是否为数字。加载4个字节并将ESI增加4。除非您的字符存储为UTF-32,否则这是行不通的。您应该在循环之前将EAX归零并使用LODSB,或者使用
movzx EAX,byte[esi]
/
inc esi
(在最近的Intel CPU上,LODSB的值仅为2 UOP,而不是3 UOP)。此外,在
调用返回后,您的代码仍然会落入
atoi
。但是必须使用
调用
将参数放在MASM的类宏的东西为
movesi、inputBuff
加载参数的地方,这一点很好。在我看来,这只会让你更难看到真正发生的事情,而不是
movesi,[ebp+8]
(或者
[esp+4]
,如果你没有制作堆栈帧的话)。那么你是说你的代码可以工作,但只针对一位数?LODSD通过从接下来的三个字节(包括超过缓冲区末尾的2个字节)加载零来将EAX的其余部分归零?当你把这段代码包含在一个数据段中有任何其他内容的程序中时,这段代码就会中断,因为你不能指望缓冲区为零后的字节数。这对于OP和所有未来的读者来说是一个更有用的答案(这是SO的真正意义)+1这些字符串到整数的问题通常有一堆其他错误,因此它们不适合作为重复问题来结束其他问题。这个问题实际上可以作为一个规范的字符串到整数的问题来解决,并且没有16位DOS I/O代码或任何东西。