【问题标题】:Converting string to integer in MASM: esi difficulty在 MASM 中将字符串转换为整数:esi 难度
【发布时间】:2012-12-01 23:22:18
【问题描述】:

我用汇编语言 (MASM) 编写了一个程序,让学生练习计算组合。程序随机分配 n 和 r,计算组合,然后提示学生提供答案。 问题已解决 *在大多数情况下,程序运行良好,但我遇到了一些挑战,将学生提供的整数字符串转换为整数,然后可以将其与程序计算的结果进行比较.我之前使用过 esi 没有问题,但是无论出于何种原因,当程序到达要评估 esi 的内容(或字符串的地址)并将其转换为整数的点时,调试器会显示内容的 esi 不是字符串中的第一个字符。* 为了清楚起见,我对 ReadInt 很熟悉,但我想弄清楚如何在不使用 ReadInt 的情况下解析整数。

更新:只要用户输入有效数字,程序现在就可以正常运行。我已经解决了 esi 没有指向正确位置的问题。我还进行了一些错误检查,以确保输入的值实际上是数字。但是,最初的错误检查意味着在下一次迭代期间输入有效数字时,在输入无效输入后,程序会不断返回消息“无效输入”。将 tryAgain 标记放在代码的第一行会导致程序继续返回无效输入消息,即使有效输入跟随无效输入也是如此。首先,我尝试将 tryAgain 标记放在其当前位置,但我认为它在无限循环中运行。其次,如果程序跳转到 invalidInput,我尝试重置变量,但这并没有修复它(我在原始位置和当前位置使用 tryAgain 进行了尝试)。

编辑:澄清一下,这是针对 x86 处理器的。

代码如下:

.data
result  DWORD   ?
temp        BYTE        21 DUP(0)
answer  DWORD   ?

.code
main    PROC

(一些初步的过程调用)

push OFFSET temp        ;ebp+16
push OFFSET answer      ;ebp+12
push answerSize     ;ebp+8
call    getData

(更多过程调用)

exit        ; exit to operating system
main ENDP

编辑代码:

;*************************************************
; prompts / gets the user’s answer.
; receives: the OFFSET of answer and temp and value of answerSize
; returns: none
; preconditions: none
; registers changed:  eax, ebx, ecx, edx, ebp, esi, esp
;*************************************************
getData PROC
push        ebp
mov     ebp,esp

tryAgain:
mWriteStr   prompt_1
mov     edx, [ebp+16]       ;move OFFSET of temp to receive string of integers
mov     ecx, 12
call        ReadString
cmp     eax, 10
jg      invalidInput

mov     ecx, eax        ;loop for each char in string
mov     esi,[ebp+16]    ;point at char in string

pushad
loopString:             ;loop looks at each char in string
    mov     ebx,[ebp+12]
    mov     eax,[ebx]   ;move address of answer into eax
    mov     ebx,10d     
    mul     ebx         ;multiply answer by 10
    mov     ebx,[ebp+12]    ;move address of answer into ebx
    mov     [ebx],eax       ;add product to answer
    mov     al,[esi]        ;move value of char into al register
    inc     esi         ;point to next char
    sub     al,48d      ;subtract 48 from ASCII value of char to get integer  

    cmp     al,0            ;error checking to ensure values are digits 0-9
    jl      invalidInput
    cmp     al,9
    jg      invalidInput

    mov     ebx,[ebp+12]    ;move address of answer into ebx
    add     [ebx],al        ;add int to value in answer

    loop        loopString  
popad
jmp     moveOn
invalidInput:               ;reset registers and variables to 0
    mov     al,0
    mov     eax,0
    mov     ebx,[ebp+12]
    mov     [ebx],eax
    mov     ebx,[ebp+16]
    mov     [ebx],eax       
    mWriteStr   error
    jmp     tryAgain
moveOn:
    pop     ebp
    ret     12
getData ENDP

只是为了让你知道我要做什么,这是我的伪代码:

伪代码已更新

  1. 从字符串的开头开始

  2. 将 answer 的值乘以 10。

  3. 从字符串中拆分每个字符并减去 48d 以获得整数。前任。学生输入 156。49 存储为变量 temp 中的第一个字符。 49减去48,整数为1。

  4. 将整数添加到答案的值。

  5. Inc esi(向右移动一个字符)。

  6. 循环。

【问题讨论】:

  • 注意add [ebx],al ;add int to value in answer是一个8位加法,所以当有进位时它不起作用。尝试解析数字 259。您应该使用 movzx 将您的数字扩展到 32 位并使用 32 位加法。

标签: assembly x86 masm


【解决方案1】:

从字符串中拆分每个字符并除以 48d。

你想减,而不是除。

关于esi的问题,请说明这个函数是如何调用的。可能[ebp+16] 不是缓冲区的偏移量,或者存在缓冲区溢出。您还可以使用调试器在该地址上设置内存写入监视,并查看谁更改了它。

另外,您的invalidInput 标签不在代码中,但我怀疑tryAgain 标签放错了位置。在序幕之后你可能想要它。

顺便说一句,进行这种转换的典型方法是从字符串的开头向前,并在每一步中将部分结果乘以 10。这样你就不需要PowerTen 函数了。

更新:您正在加载 4 个字节,因此一次从您的字符串中加载 4 个字符,这就是您看到意外值的原因。而不是mov eax,[esi]movzx eax, [esi]mov al, [esi]

【讨论】:

  • 关于过程如何调用,你的意思是getData吗?如果是这样,则显示在 main 中调用,并在调用之前将参数压入堆栈。我为每次推送提供了 cmets 以显示其在 ebp 中的位置。抱歉,我在剪切和粘贴时错过了 invalidIput 和 tryAgain。我现在正在编辑代码。
  • 好建议。我正在努力,并将发布更新。
【解决方案2】:

[esi] 中的当前字符串索引指针移动一个字节 您需要使用以下其中一项:

movzx   eax, byte ptr[esi]
; or
mov     al, byte ptr[esi]

BYTE PTR 告诉 MASM 你想处理 esi 中地址的一个字节。

我不确定你是否希望这样:

tryAgain:
    push    ebp
    mov     ebp, esp
    mWriteStr   prompt_1 

因为每次用户输入一个错误的提示,你跳到tryAgain,你一直在“设置堆栈”。也许是这样:

    push    ebp
    mov     ebp, esp

tryAgain:
    mWriteStr   prompt_1 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-27
    • 2012-02-21
    • 2010-12-31
    相关资源
    最近更新 更多