Question

I've written a small program in x86-64 assembly (AT&T) syntax, and it assembles just fine, but I don't get the result I expected. I have a variable in register %rdi, which I need to modify in a subroutine, and I need to keep the original value for some other usage later. What I want to do is to push the original value onto the stack, and then retrieve it again when the subroutine finishes, for example, if the variable is located in %rdi.

    pushq %rdi
    call subroutine
    movq (%rsp), %rdi

Now, I'm not really sure if this is the correct way to do it? I've read somewhere that a subroutine pushes the return value onto of the stack, but does that mean that I have to include an offset when I try to retrieve the variable?

Also I know I have to keep the stack pointer aligned by 16 bytes, which I'm not quite sure if I do. In case I don't, will the assembler then give me an error, or could that be the reason why my program fails?

And by the way, this program is part of an assignment, so I cannot share the code with you, but I hope my description is good enough.

Was it helpful?

Solution

The code fragment is suspicious in that it fails to keep the stack pointer balanced across a call sequence, which is probably not the intended behaviour. Typically you would either match push and pop operations, push many times and then addq $k, %rsp (where k is the combined size of every previous push), or keep the frame size constant across the execution of the function and use explicit accesses.

Given that you need to keep keep the stack pointer 16-byte aligned, keeping a constant-sized frame is probably the most straightforward method. It might look like

# in the function prologue
subq $K, %rsp
...
mov %rdi, SLOT(%rsp)
call subroutine
mov SLOT(%rsp), %rdi
...
# in the epilogue
addq $K, %rsp

Where K is enough space for all the local stack state plus enough space for the largest set of outgoing arguments, rounded up to 16, and SLOT is a spot on the stack reserved for the value of %rdi.

The return value of an integer type usually placed in rax, not on the stack. Other types are returned differently (such as by a hidden pointer) - check the calling convention of the compiler you are interfacing with.

OTHER TIPS

Instead of movq (%rsp),%rdi, use popq %rdi . The first doesn't update the RSP stack pointer, so you could be in a problem when returning to the function that called you.

This, of course, if subroutine doesn't adjust the stack for itself. It subroutine is using the standard (Pascal) calling convention, parameters will be removed by the function itself, and not the caller, and you will loose access to the saved %rdi value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top