x86 NASM Assembly - Problems with Input

前端 未结 2 1295
难免孤独
难免孤独 2021-01-20 12:51

I am working to take input from a user twice, and compare the input. If they are the same, the program exits. If not, it reprints the input from the first time, and waits fo

相关标签:
2条回答
  • You are assuming sys.read returns the entire line. It is not required to do so. It may return after only one character, or even possibly after part of the second line.

    You know, this kind of thing kind of ticks me off. This looks like a homework problem in writing in assembly, but the problem is not with the assembly, but with the assumptions in how the system calls work.

    I really wish the instructors would provide an fgets library function for stuff like this.

    Anyway, the stupid way to fix it is to read one byte at a time, looking for LF (byte 10) to end the loop.

    0 讨论(0)
  • 2021-01-20 13:25

    Apart from what @Joshua is pointing out, you're not comparing your strings correctly.

    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)
    

    Firstly, when you have e.g. label dd 1234 in your data segment mov eax, label will move the address of label to eax while mov eax, [label] will move the contents stored at label (in this case 1234) into eax.

    Note that in the above example I deliberately used a 32-bit variable so that it would fit neatly into eax. If you're using byte sized variables (like ascii characters) e.g. mybyte db 0xfe you'll either have to use byte sized register (al, ah, dh etc.) or use the move with zero/sign extend opcodes: movzx eax, byte [mybyte] will set eax to 254, while movsx eax, byte [mybyte] will set eax to -2 (0xfffffffe).

    You also need to do a character by character comparison of the strings. Assuming you save the read string length (you really should be checking for negative return values - meaning errors) in input_len and check_len it could look something like:

        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
    

    If you're interested in another way of doing this in fewer instructions look up rep cmpsb.

    There are a few other problems in the code immediately following your checker code. The pop edx instruction (and the code following, down to the loop label) will not be execute as you're always jumping either to loop or done.

    jne loop    ;if not the same go to input again
    je done     ;else go to the end
    pop edx   ; Will never be reached!
    

    The reason you're getting funny characters is from newlineL: db $-newline This should be equ instead of db or you should replace mov edx, newlineL with movzx edx, byte [newlineL]. Since newlineL unlike the other *L names refers to a variable and not a constant equ mov edx, newlineL will use the address of the newlineL variable as the number of bytes to write, when you wanted it to be 1.

    0 讨论(0)
提交回复
热议问题