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
