Reputation: 135
I converted a very simple C program to an assembly file (Here, RISC-V ISA), and there were some operations done on the stack pointer that I did not understand.
The C program :
int main()
{
int a = 10;
return 0;
}
The associated assembly code :
.file "alternating_branches_2.c"
.option nopic
.text
.align 1
.globl main
.type main, @function
main:
addi sp,sp,-32
sd s0,24(sp)
addi s0,sp,32
li a5,10
sw a5,-20(s0)
li a5,0
mv a0,a5
ld s0,24(sp)
addi sp,sp,32
jr ra
.size main, .-main
.ident "GCC: (GNU) 8.3.0"
Here is my understanding.
sp contains the last address of the stack memory. Pushing to stack would, therefore, decrease the value of sp. s0 is the frame pointer, pointing to the previous value of sp.
In the first line, an offset of 32 is decreased from the stack pointer. Is this to create a stack frame? And usually, in a stack, a push operation would decrease the stack pointer. However, since a stack frame is already created, and sp now points to lower memory of stack, will pushing increase the value of sp?
-------------| <--sp
-------------|
-------------|
-------------|
-------------|
-------------|
-------------|
After the creation of the stack frame :
-------------| <--s0
-------------|
-------------|
-------------|
-------------|
-------------|
-------------| <--sp
And now, pushing to the stack must result in an increase in sp, correct? Or can pushing also be done using the frame pointer, s0? I apologize if this is a very basic question. Thank you.
Upvotes: 7
Views: 2431
Reputation: 24788
Unlike the x86 ISA – which has dedicated instructions for pushing onto and popping from the stack, the RISC-V ISA can only access memory through load and store instructions. It has no push and pop instructions that access the stack – which is the memory – and modify the stack pointer.
Since the stack grows downwards, decreasing the stack pointer, sp
, allocates space on the stack, whereas increasing it deallocates space. That is, addi sp,sp,-32
allocates 32 bytes on the stack and addi sp,sp,32
deallocates 32 bytes from the stack. The former creates the new stack frame, and the latter destroys it.
The s0
register – which is the same as fp
– is the frame pointer and points to the beginning of the stack frame. Its current value is saved at the very beginning of the newly created stack frame (sd s0,24(sp)
). Then, it is set to the address pointing at the beginning of the stack frame (addi s0,sp,32
). Finally, the frame pointer is restored with its previous value (ld s0,24(sp)
) before leaving the function.
The representation of the stack after the stack frame creation and the frame pointer setup is:
| ... |
|-------------|<- s0 | beginning of stack frame
| previous s0 |
|-------------|<- sp-24
|-------------|
|-------------|
|-------------|
|-------------|
|-------------|
|-------------|
|-------------|<- sp | end of stack frame
Upvotes: 6