I'm trying to implement a simple addition calculator, but I'm not able to store the input in my array. I'm trying to read char by char because I want to use it later to implement a backend for my B compiler (which has the getchar function that reads char by char from stdin). My code is the fallowing:
segment .data
numb db 0, 0, 0, 0
indx db 0
char db '0'
newl db 0ah
msg1 db 'enter a number: '
len1 equ $ - msg1
segment .text
global _start ; defines the entry point
print: ; push msg; push len
pop eax ; removes caller address from stack
pop edx ; gets length
pop ecx ; gets msg
push eax ; pushes CA to stack again
mov ebx , 01h ; tells that it's an output call
mov eax , 04h ; system call (write)
int 80h ; calls it
ret
getc: ; push add; push len
pop eax ; removes caller address from stack
pop ecx ; gets ouput addrress
push eax ; pushes CA to stack again
mov edx , 01h
mov ebx , 00h ; tells that it's an input call
mov eax , 03h ; system call (read)
int 80h ; calls it
ret
exit:
mov ebx , 0 ; sets exit code
mov eax , 01h ; system call (exit)
int 80h ; calls it
_start:
push msg1
push len1
call print
read:
push char
call getc
mov eax , numb
add eax , indx
mov [eax], dword char
inc byte [indx]
mov eax , char
cmp eax , newl
jne read
jmp exit ; exits program
for now I'm just trying to store the input, because I got segfaults from the complete code, so I started stripping off code until I found the error cause.
CodePudding user response:
You probably don't want to insert the newline in the array, so start with checking for the newline:
read:
push char
call getc
mov al, [char]
cmp al, 10
je done
Then load the byte-sized index in an address register, remembering that AL
already contains the datum, so pick another register than EAX
. Also, instead of adding the array address numb and the index indx yourself, let the CPU do that for your with an addressing mode that has a displacement component ([numb ebx]
):
movzx ebx, byte [indx]
mov [numb ebx], al
inc byte [indx]
jmp read
done:
jmp exit
There's also the possibility to define the index indx as a dword with indx dd 0
. Then the code becomes:
read:
push char
call getc
mov al, [char]
cmp al, 10
je done
mov ebx, [indx]
mov [numb ebx], al
inc dword [indx]
jmp read
done:
jmp exit
The lesson here is that NASM is different from MASM in how you address memory:
MASM
mov eax, offset MyVar ; Load address of MyVar
mov eax, MyVar ; Load value stored in MyVar
NASM
mov eax, MyVar ; Load address of MyVar
mov eax, [MyVar] ; Load value stored in MyVar