factor_plain.s: .text .globl factor factor: addi sp,sp,-32 sd ra,24(sp) sd s0,16(sp) addi s0,sp,32 sd a0,-24(s0) ld a5,-24(s0) bne a5,zero,.L2 li a5,1 j .L3 .L2: ld a5,-24(s0) addi a5,a5,-1 mv a0,a5 call factor mv a4,a0 ld a5,-24(s0) mul a5,a4,a5 .L3: mv a0,a5 ld ra,24(sp) ld s0,16(sp) addi sp,sp,32 jr ra 为什么src/lab4-1/factor_plain.s中factor函数的入口处需要执行sd ra, 24(sp)指令,而src/lab4-1/acc_plain.s中的acc函数并没有执行该指令? 请解释在call factor前的mv a0, a5这条汇编指令的目的。 请简要描述调用factor(10)时栈的变化情况;并回答栈最大内存占用是多少,发生在什么时候。 假设栈的大小为4KB,请问factor(n)的参数n最大是多少?
时间: 2023-06-17 13:08:19 浏览: 150
u-boot-1_1_6_start_S代码笔记
1. 在src/lab4-1/factor_plain.s中,因为factor函数可能会调用其他函数,需要保存调用者(ra)的值,以便在函数返回后能够正确返回到调用方。而在src/lab4-1/acc_plain.s中的acc函数没有调用其他函数,因此不需要保存ra的值。
2. mv a0, a5的目的是将参数a5的值复制到寄存器a0中,以便在调用factor函数时能够正确传递参数。
3. 调用factor(10)时,栈的变化情况如下:
- addi sp, sp, -32:将栈指针向下移动32个字节,为函数调用分配栈空间。
- sd ra, 24(sp):保存调用者(ra)的值。
- sd s0, 16(sp):保存调用者的栈指针(s0)。
- addi s0, sp, 32:将栈指针保存到s0寄存器中。
- sd a0, -24(s0):保存参数a0的值到栈上。
- ld a5, -24(s0):将参数a0的值加载到a5寄存器中。
- bne a5, zero, .L2:如果a5不等于0,则跳转到.L2标签处。
- li a5, 1:将a5设置为1。
- j .L3:跳转到.L3标签处。
- .L2: ...
- .L3: ...
- mv a0, a5:将a5的值复制到a0中,以便传递给factor函数。
- call factor:调用factor函数。
- mv a4, a0:将factor的返回值保存到a4寄存器中。
- ld a5, -24(s0):将参数a0的值加载到a5寄存器中。
- mul a5, a4, a5:计算a4和a5的乘积并将结果保存到a5中。
- mv a0, a5:将a5的值复制到a0中,作为函数的返回值。
- ld ra, 24(sp):恢复调用者(ra)的值。
- ld s0, 16(sp):恢复调用者的栈指针(s0)。
- addi sp, sp, 32:释放栈空间。
栈的最大内存占用为32字节,发生在调用factor函数时。
4. 假设栈的大小为4KB,每个栈帧占用32字节,因此最多可以创建4KB/32B=128个栈帧。每个栈帧中需要保存的信息有ra、s0和a0-a5共7个寄存器,每个寄存器占用8字节,因此每个栈帧需要保存的信息共占用7*8=56字节。因此,最大的factor参数n为128,即调用factor(128)时栈的空间刚好用完。
阅读全文