为什么这个 MIPS 代码在调用函数时为 8 个寄存器而不是 4 个分配空间?
我在互联网上找到了这个样本 spim 代码
.data
COUNT: .word 10
TEXT: .asciiz "The number is "
EOL: .asciiz "\n"
.text
.globl main
main:
addiu $sp, $sp, -32 # Adjust stack
sw $ra, 24($sp)
sw $fp, 16($sp) # save old frame pointer
addiu $fp, $sp, 28 # load new frame pointer
la $t0, COUNT
lw $t1, 0($t0)
li $t0, 0 # init index to 0
loop:
sw $t0, 12($sp) # save caller saved registers
sw $t1, 8($sp) #
move $a0, $t0 # setup parameter for fn call
jal print_num # call subroutine
lw $t1, 8($sp) # restore caller saved values
lw $t0, 12($sp) #
addiu $t0, $t0, 1 # increment index;
blt $t0, $t1, loop #
lw $fp, 16($sp) # restore frame pointer
lw $ra, 24($sp) # restore return address
addiu $sp, $sp, 32 # restore stack pointer
jr $ra
如果 main 函数需要将四个寄存器保存到堆栈上($ra $fp $t0 $t1),它为什么会为 8 个寄存器分配空间(32 字节而不是 16 字节)?
I found this sample spim code on the internet
.data
COUNT: .word 10
TEXT: .asciiz "The number is "
EOL: .asciiz "\n"
.text
.globl main
main:
addiu $sp, $sp, -32 # Adjust stack
sw $ra, 24($sp)
sw $fp, 16($sp) # save old frame pointer
addiu $fp, $sp, 28 # load new frame pointer
la $t0, COUNT
lw $t1, 0($t0)
li $t0, 0 # init index to 0
loop:
sw $t0, 12($sp) # save caller saved registers
sw $t1, 8($sp) #
move $a0, $t0 # setup parameter for fn call
jal print_num # call subroutine
lw $t1, 8($sp) # restore caller saved values
lw $t0, 12($sp) #
addiu $t0, $t0, 1 # increment index;
blt $t0, $t1, loop #
lw $fp, 16($sp) # restore frame pointer
lw $ra, 24($sp) # restore return address
addiu $sp, $sp, 32 # restore stack pointer
jr $ra
If function main needs to save four registers onto the stack ($ra $fp $t0 $t1), how come it allocates space for 8 registers (32 bytes instead of 16 bytes)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
帧指针应指向堆栈的开头(底部)。由于堆栈元素为 4 个字节,因此底部元素的起始位置比堆栈大小小 4。
The frame pointer should point to the beginning (bottom) of the stack. Since the stack elements are 4 bytes, the start of the bottom element is 4 less than the size of the stack.
这是由于使用了约定,特别是调用约定。在MIPS中,如果被调用者需要使用一些寄存器,则将它们保存在堆栈上,哪些寄存器需要保存以及它们保存在堆栈中的位置是在某些约定中指定的。我不知道关于 SPIM,但 SGI IRIX 有两种不同的约定,称为
o32
和n32
(表示“旧”和“新”),您可能会幸运地在谷歌上搜索它们。This is due to the use of a convention, in particular a calling convention. In MIPS, the calleé saves some registers on the stack if it needs to use them, which registers need saving and where in the stack they are saved is specified in some convention. IDK about SPIM, but SGI IRIX had two different conventions called
o32
andn32
(for "old" and "new"), you may have some luck googling for them.