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个版本。