How do I handle the stack pointer register when returning from an assembly function call to a C program?

172 Views Asked by At

My program is composed of two files: main.c and core.s and runs on a 32 bit virtual machine of lubuntu linux.

Main.c takes in an integer and passes it to the assembly function void printFunc(int x). The assembly function in turn calls to a C function to check the parity of x. If x is even the function will print 4x and if x is odd it will print 8x. The print call must be done within the assembly function.

section .text
    global printFunc
    extern c_checkValidity
    extern printf

section .data       ; data section

fmt: db "%d", 10, 0 ; The printf format, "\n", '0'
            
printFunc:
    push ebp                ; code for handling stack I've seen from
    mov ebp, esp            ; other examples online
    pushad                  
    mov ebx, eax            ; copy and input value
    push eax                ; Move input onto stack
    call c_checkValidity    ; Call C function, return value is in eax   
    cmp eax, 1              ; Check result, 1 indicates even
    je multby4              ; If even, do mult by 4
    jmp multby8             ; Otherwise odd, do mult by 8

multby4:                    ;INPUT WAS EVEN
    sal ebx, 2              ; left shift by 2 is equivalent to multiplying by 4 
    jmp exitcode            ; print and exit code

multby8:                    ;INPUT WAS ODD
    sal ebx, 3              ; left shift by 3 is equivalent to multiplying by 8
    jmp exitcode            ; print and exit code
    
exitcode:   
    mov eax,ebx             ; move value to eax to keep as default return value of func
    push ebx                ; Push final answer to the stack
    push dword fmt          ; Push print format to the stack
    call printf             ; Print answer
    mov eax, ebx            ; Copy final answer as return value
    popad
    mov esp, ebp            ; return stack pointer to what it was before operation
    pop ebp                 ; get rid of saved pointer
    ret                     ; return state to caller

The integer input is received, parity tested, and printed to stdout correctly. A segfault occurs somewhere after call printf has successfully executed. When I use gdb to try and backtrace the segfault the report says "0x0804a0f in exitcode ()". Presumably this is the address of the code during operation that causes the segfault?

It is clear to me that I have failed to properly handle the stack pointer register (esp?) in some way. I've tried searching this site and others for examples of how to properly address the stack before returning control to the caller but to no avail. Certainly I would love to make the code work and any advice on how to fix the code is appreciated but I am primarily asking for an explanation on what I should be tracking and maintaining in general to return from an assembly function to a caller (extra appreciation if that explanation includes how to pass back values to the caller).

0

There are 0 best solutions below