Loops x86 NASM程序集-输入问题
我正在努力从用户那里获取两次输入,并比较输入。如果它们相同,则程序退出。如果没有,它将重新打印第一次输入的内容,并等待用户键入内容。如果它是相同的,同样的事情会发生。如果不是这样,就会发生与以前相同的事情 输入和循环不是问题所在。主要问题是我从程序中得到的结果。以下是我在代码方面所做的工作:Loops x86 NASM程序集-输入问题,loops,assembly,input,nasm,Loops,Assembly,Input,Nasm,我正在努力从用户那里获取两次输入,并比较输入。如果它们相同,则程序退出。如果没有,它将重新打印第一次输入的内容,并等待用户键入内容。如果它是相同的,同样的事情会发生。如果不是这样,就会发生与以前相同的事情 输入和循环不是问题所在。主要问题是我从程序中得到的结果。以下是我在代码方面所做的工作: %include "system.inc" section .data greet: db 'Hello!', 0Ah, 'Please enter a word or characte
%include "system.inc"
section .data
greet: db 'Hello!', 0Ah, 'Please enter a word or character:', 0Ah
greetL: equ $-greet ;length of string
inform: db 'I will now repeat this until you type it back to me.', 0Ah
informL: equ $-inform
finish: db 'Good bye!', 0Ah
finishL: equ $-finish
newline: db 0Ah
newlineL: equ $-newline
section .bss
input: resb 40 ;first input buffer
check: resb 40 ;second input buffer
section .text
global _start
_start:
greeting:
mov eax, 4
mov ebx, 1
mov ecx, greet
mov edx, greetL %include "system.inc"
section .data
greet: db 'Hello!', 0Ah, 'Please enter a word or character:', 0Ah
greetL: equ $-greet ;length of string
inform: db 'I will now repeat this until you type it back to me.', 0Ah
informL: equ $-inform
finish: db 'Good bye!', 0Ah
finishL: equ $-finish
newline: db 0Ah
newlineL: db $-newline
section .bss
input: resb 40 ;first input buffer
check: resb 40 ;second input buffer
section .text
global _start
_start:
greeting:
mov eax, 4
mov ebx, 1
mov ecx, greet
mov edx, greetL
sys.write
getword:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 40
sys.read
sub eax, 1 ;remove the newline
push eax ;store length for later
instruct:
mov eax, 4
mov ebx, 1
mov ecx, inform
mov edx, informL
sys.write
pop edx ;pop length into edx
mov ecx, edx ;copy into ecx
push ecx ;store ecx again (needed multiple times)
mov eax, 4
mov ebx, 1
mov ecx, input
sys.write
mov eax, 4 ;print newline
mov ebx, 1
mov ecx, newline
mov edx, newlineL
sys.write
mov eax, 3 ;get the user's word
mov ebx, 0
mov ecx, check
mov edx, 40
sys.read
xor eax, eax
checker:
mov ebx, check
mov ecx, input
cmp ebx, ecx ;see if input was the same as before
jne loop ;if not the same go to input again
je done ;else go to the end
pop edx
mov ecx, edx
push ecx
mov eax, 4
mov ebx, 1
mov ecx, check
sys.write ;repeat the word
mov eax, 4
mov ebx, 1
mov ecx, newline
mov edx, newlineL
sys.write
loop:
mov eax, 3 ;replace new input with old
mov ebx, 0
mov ecx, check
mov edx, 40
sys.read
jmp checker
done:
mov eax, 1
mov ebx, 0
sys.exit
sys.write
getword:
mov eax, 3
mov ebx, 0
mov ecx, input
mov edx, 40
sys.read
我的结果现在是:编辑
Hello!
Please enter a word or character:
Nick
I will now repeat this until you type it back to me.
Nick
(I input) Magerko
(I get) M
(I input)Nick
(I get)
(I input)Nick
(I get)
编辑
这种情况还在继续。我的检查没有按照上面代码中的预期工作,最终我甚至不能让程序打印任何东西,除了换行符。这有什么原因吗
谢谢。您假设sys.read返回整行。不需要这样做。它可能只在一个字符之后返回,甚至可能在第二行的一部分之后返回 你知道,这种事让我很生气。这看起来像是在汇编中编写作业的问题,但问题不在于汇编,而在于系统调用如何工作的假设 我真的希望讲师能为这样的东西提供fgets库函数
无论如何,解决这个问题的愚蠢方法是一次读取一个字节,寻找LF(字节10)来结束循环。除了@Joshua指出的以外,你没有正确比较字符串
checker:
mov ebx, check ; Moves the *address* of check into ebx
mov ecx, input ; Similarly for input
cmp ebx, ecx ; Checks if the addresses are the same (they never are)
首先,当您的数据段mov-eax中有例如label dd 1234
时,label
将label
的地址移动到eax
,而mov-eax,label
将label
中存储的内容移动到eax
请注意,在上面的示例中,我特意使用了一个32位变量,以便将其整齐地放入eax
。如果您使用字节大小的变量(如ascii字符),例如mybyte db 0xfe
,则必须使用字节大小的寄存器(al
,ah
,dh
等),或者使用带有零/符号扩展操作码的移动:movzx eax,byte[mybyte]
将eax设置为254,而movsx eax,byte[mybyte]
将eax设置为-2(0xfffffffe
)
您还需要对字符串进行逐个字符的比较。假设您在input\u len
和check\u len
中保存读取字符串长度(您确实应该检查负返回值-表示错误),它可能看起来像:
mov eax, [input_len]
cmp eax, [check_len]
jne loop ; Strings of different length, do loop again
mov ebx, check
mov ecx, input
.checkloop:
mov dl, [ebx] ; Read a character from check
cmp dl, [ecx] ; Equal to the character from input?
jne loop ; Nope, jump to `loop`
inc ebx ; Move ebx to point at next character in check
inc ecx ; and ecx to next character in input
dec eax ; one less character to check
jnz .checkloop ; done?
; the strings are equal if we reach this point in the code
jmp done
如果您对以较少的指令执行此操作的另一种方式感兴趣,请查找rep cmpsb
紧跟在检查器之后的代码中还有一些其他问题。pop-edx
指令(以及下面的代码,一直到loop
标签)将不会执行,因为您总是跳转到loop
或done
jne loop ;if not the same go to input again
je done ;else go to the end
pop edx ; Will never be reached!
你得到有趣字符的原因是来自newlineL:db$-newline
这应该是eq
而不是db
,或者你应该用movzx-edx,byte[newlineL]
替换mov-edx,newlineL
。由于newlineL
与其他*L
名称不同,名称指的是变量,而不是常量eq
mov-edx,因此当希望变量的地址为1时,newlineL
将使用newlineL
变量的地址作为要写入的字节数 那么你有什么建议来解决这个问题呢?我的程序中假设这一点的部分是什么?非常深入的回答。这对我以后真的很有帮助!我只是在想我是如何使用db而不是equ lol的。非常有用。我将着手解决它。@user786653我试图修复您建议的问题,但我认为我没有正确地实现它。我应该试试别的吗?你应该提出一个新问题。记住要事先清理代码,目前看起来您混合了2或3个版本。