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
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.
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.