MIPS 堆栈指针

MIPS stack pointer

在这里感觉有点傻,试图弄清楚这条线在做什么:

addiu   sp,sp,-24

我理解是设置栈指针,我的困惑是addiu部分。它将 UNSIGNED -24 添加到堆栈指针,并将其存储回堆栈指针。

sp是取16位的值-24(FFE8)(addiu运算的"immediate"值是16位宽)还是它将符号扩展到完整的 32 位?

另外,sp=0是在这条指令之前吗?它是一小段 C 代码中的第一条指令。

我正在将 MIPS 内核作为个人项目来实现,这让我有些困惑。

算术指令

MIPS 支持四种基本算术运算:加法、减法、乘法和 师.

加法指令:基本加法指令

 add Rdest,Rsrc1,Rsrc2

Rsrc1Rsrc2的内容相加并将结果存储在Rdest中。这些数字被视为有符号整数。如果发生溢出,则会生成溢出异常。 addu如果不需要溢出异常就可以使用

第二个操作数可以指定为immediate 16-bit number。格式为:

 addi Rdest,Rsrc1,imm

16-bit 的值为 sign-extended to 32 bits 并添加到 Rsrc1 的内容中。与 add 指令一样,会产生溢出异常。与添加一样,如果不需要溢出异常,我们可以使用addiu

堆栈实现

MIPS 不明确支持堆栈操作。相比之下,它 提供push、pop等指令,方便栈操作。此外,还有一个特殊的栈指针寄存器sp,用来保存栈顶信息。在 MIPS 中,寄存器扮演堆栈指针的角色。我们必须操作这个寄存器来实现堆栈。

例如,堆栈向下增长(即,当我们将项目压入堆栈时,地址减少)。因此,当在堆栈上保留 space 用于压入值时,我们必须减少 sp 值。这样,开始执行时栈指针的相对值可以取为零。

例如,要压入​​寄存器 a0ra,我们必须保留八个字节的堆栈 space 并使用 sw 压入值,如下所示:

sub $sp,$sp,8 # reserve 8 bytes of stack
sw $a0,0($sp) # save registers
sw $ra,4($sp)

这个序列通常用在保存寄存器的程序开始处。要在从过程返回之前恢复这些寄存器,我们可以使用以下序列:

lw $a0,0($sp) # restore the two registers
lw $ra,4($sp)
addu $sp,$sp,8 # clear 8 bytes of stack

所以,第一个问题的答案:

The 16-bit value is sign-extended to 32 bits and added to the contents of Rsrc1.

关于你的第二个问题:

Thus, the relative value of the stack pointer at the beginning of execution could be taken as zero.

The addiu instruction includes a 16-bit immediate operand. When the ALU executes the instruction, the immediate operand is sign-extended to 32 bits. If two's complement overflow occurs during the addition, it is ignored.

addiu   d,s,const        # $d <—— s + const. 
                         # Const is 16-bit two's comp. sign-extended to 32 bits
                         # when the addition is done. No overflow trap.