Search code examples
linuxassemblyx86addition

Add 2 numbers and print the result using Assembly x86


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.


Solution

  • You're popping 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.