Reputation: 201
I'm a novice Assembly x86 Learner, and i want to add two numbers (5+5) and print the result on the screen.
here is my code:
global _start
section .text
_start:
mov eax, 5
mov ebx, 5
add eax, ebx
push eax
mov eax, 4 ; call the write syscall
mov ebx, 1 ; STDOUT
pop ecx ; Result
mov edx, 0x1
int 0x80
; Exit
mov eax, 0x1
xor ebx, ebx
int 0x80
It exits without printing anything.
Upvotes: 0
Views: 15148
Reputation: 14399
You're pop
ping the value 10
into ECX, and passing that to a write
system call as the address. It's not a valid address so it returns -EFAULT
; use strace ./a.out
to see that. write(int fd_ebx, void *buf_ecx, size_t len_edx)
.
You could mov ecx, esp
to pass the address of the bytes you pushed, but that's an integer 10
(ASCII newline). You need to pass a pointer to ASCII digit characters that represent your number, like what printf
does.
One approach to convert an unsigned integer to a string and write
it, using a buffer on the stack:
section .text
global _start
_start:
mov eax, 1234567890
mov ebx, 5
add eax, ebx
; Convert EAX to ASCII and store it onto the stack
sub esp, 16 ; reserve space on the stack
mov ecx, 10
mov ebx, 16
.L1:
xor edx, edx ; Don't forget it!
div ecx ; Extract the last decimal digit
or dl, 0x30 ; Convert remainder to ASCII
sub ebx, 1
mov [esp+ebx], dl ; Store remainder on the stack (reverse order)
test eax, eax ; Until there is nothing left to divide
jnz .L1
mov eax, 4 ; SYS_WRITE
lea ecx, [esp+ebx] ; Pointer to the first ASCII digit
mov edx, 16
sub edx, ebx ; Count of digits
mov ebx, 1 ; STDOUT
int 0x80 ; Call 32-bit Linux
add esp, 16 ; Restore the stack
mov eax, 1 ; SYS_EXIT
xor ebx, ebx ; Return value
int 0x80 ; Call 32-bit Linux
See also How do I print an integer in Assembly Level Programming without printf from the c library? (itoa, integer to decimal ASCII string) for more background on the algorithm of repeated division by 10, an x86-64 assembly version, and ways to do it more efficiently.
Upvotes: 4