我用汇编语言(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
这样你就可以了解我的目标,这是我的伪代码:
伪代码已更新
从字符串的开头
将答案的值乘以10。
从字符串中拆分每个字符并减去48d以获得整数。防爆。学生输入156. 49被存储为变量temp中的第一个char。从49减去48.整数是1.
将整数添加到答案值。
Inc esi(向右移动一个字符)。
循环。
答案 0 :(得分:1)
将每个字符从字符串中拆分并除以48d。
你想减去而不是分裂。
关于esi
问题,请说明如何调用此函数。也许[ebp+16]
不是缓冲区的偏移量,或者存在缓冲区溢出。您还可以使用调试器在该地址上设置内存写入监视,并查看更改者。
此外,您的invalidInput
标签不在代码中,但我怀疑tryAgain
标签位于错误的位置。你可能在序幕之后想要它。
顺便说一下,执行此转换的典型方法是从字符串的开头向前,并在每一步中将部分结果乘以10。这样您就不需要PowerTen
函数。
更新:您正在加载4个字节,因此您的字符串会同时加载4个字符,这就是您看到意外值的原因。而不是mov eax,[esi]
执行movzx eax, [esi]
或mov al, [esi]
答案 1 :(得分:0)
从[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