Skip to content
Advertisement

push/pop segmentation fault in simple multiplication function

my teacher is doing a crash course in assembly with us, and I have no experience in it whatsoever. I am supposed to write a simple function that takes four variables and calculates (x+y)-(z+a) and then prints out the answer. I know it’s a simple problem, but after hours of research I am getting no where, any push in the right direction would be very helpful! I do need to use the stack, as I have more things to add to the program once I get past this point, and will have a lot of variables to store. I am compiling using nasm and gcc, in linux. (x86 64)

(side question, my ‘3’ isn’t showing up in register r10, but I am in linux so this should be the correct register… any ideas?)

Here is my code so far:

    global main

    extern printf

segment .data

    mulsub_str  db  "(%ld * %ld) - (%ld * %ld) = %ld",10,0

    data            dq  1, 2, 3, 4
segment .text

main:

    call multiplyandsubtract
    pop r9
    mov rdi, mulsub_str
    mov rsi, [data]
    mov rdx, [data+8]
    mov r10, [data+16]
    mov r8, [data+24]
    mov rax, 0
    call printf

    ret



multiplyandsubtract:

    ;;multiplies first function
    mov rax, [data]
    mov rdi, [data+8]
    mul rdi
    mov rbx, rdi
    push rbx

    ;;multiplies second function
    mov rax, [data+16]
    mov rsi, [data+24]
    mul rsi
    mov rbx, rsi
    push rbx

    ;;subtracts function 2 from function 1
    pop rsi
    pop rdi
    sub rdi, rsi
    push rdi
    ret

Advertisement

Answer

push in the right direction

Nice pun!

Your problem is that you apparently don’t seem to know that ret is using the stack for the return address. As such push rdi; ret will just go to the address in rdi and not return to your caller. Since that is unlikely to be a valid code address, you get a nice segfault.

To return values from functions just leave the result in a register, standard calling conventions normally use rax. Here is a possible version:

    global main

    extern printf

segment .data

    mulsub_str  db  "(%ld * %ld) - (%ld * %ld) = %ld",10,0

    data            dq  1, 2, 3, 4
segment .text

main:
    sub rsp, 8
    call multiplyandsubtract
    mov r9, rax
    mov rdi, mulsub_str
    mov rsi, [data]
    mov rdx, [data+8]
    mov r10, [data+16]
    mov r8, [data+24]
    mov rax, 0
    call printf
    add rsp, 8

    ret



multiplyandsubtract:

    ;;multiplies first function
    mov rax, [data]
    mov rdi, [data+8]
    mul rdi
    mov rbx, rdi
    push rbx

    ;;multiplies second function
    mov rax, [data+16]
    mov rsi, [data+24]
    mul rsi
    mov rbx, rsi
    push rbx

    ;;subtracts function 2 from function 1
    pop rsi
    pop rdi
    sub rdi, rsi
    mov rax, rdi
    ret

PS: notice I have also fixed the stack alignment as per the ABI. printf is known to be picky about that too.

User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement