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 for the user to type something. If it is the same, the same thing as before occurs. If not, the same thing as before occurs.
Input and looping is not the problem. The main problem is the result I am getting from the program. My following is what I am doing codewise:
%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
My result is now: EDITED
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)
EDITED
And this continues. My checks do not work as intended in the code above, and I eventually don't even get the program to print anything but a newline. Is there a reason for this?
Thanks.
Apart from what @Joshua is pointing out, you're not comparing your strings correctly.
Firstly, when you have e.g.
label dd 1234
in your data segmentmov eax, label
will move the address oflabel
toeax
whilemov eax, [label]
will move the contents stored atlabel
(in this case 1234) intoeax
.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, whilemovsx 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
andcheck_len
it could look something like: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. Thepop edx
instruction (and the code following, down to theloop
label) will not be execute as you're always jumping either toloop
ordone
.The reason you're getting funny characters is from
newlineL: db $-newline
This should beequ
instead ofdb
or you should replacemov edx, newlineL
withmovzx edx, byte [newlineL]
. SincenewlineL
unlike the other*L
names refers to a variable and not a constantequ
mov edx, newlineL
will use the address of thenewlineL
variable as the number of bytes to write, when you wanted it to be 1.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.