赞
踩
$f0~$f31
HI, LO, PC
等$
符号,可以接名称或编号(如$a0
和$4
都表示寄存器a0)s0~s7
,被掉函数结束后调用函数还可以用这些值;如果存在t0~t7
就不能用了(C翻译汇编时要小心)Load
/Store
指令访问存储器数据op
段),6位宽。
func段
)进行区分(例如MIPS的R型指令)jr
和jalr
LOAD
系列和STORE
系列指令。寄存器RS给出基地址,16位立即数(符号扩展)给出偏移量beq
/bne
等。比较RS和RT寄存器的值,16位立即数(符号扩展)给出目标指令和当前指令偏差的条数target address
所指示的指令执行memory map
,其中Text
段用于存储指令,可见指令地址范围是0x0040_0000
到0x0FFF_FFFC
,高四位恒为0。为了避免Text段浮动导致问题,我们直接用pc寄存器(当前指令)的高四位作为目标指令的高四位pc高四位 + 26位target address + 0000
,共32位汇编:把汇编指令翻译为机器码
反汇编:把机器码翻译为汇编指令
//示例1:假定给 f, g, h, i, j分别分配 $s1, $s2, $s3, $s4, $s5 f = (g+h)-(i+j); add $t0, $s2, $s3 add $t1, $s4, $s5 sub $s1, $t0, $t1 //示例2:16位有符号立即数[-32768,32767] f = (g+100) - (i+50); addi $7, $2, 100 addi $8, $4, 50 sub $1, $7, $8 //示例3:出现的常数超过16位有符号数范围 f = (g+65000) - (i+50) addi $7, $2, 65000 //错了,因为超过16位立即数表示范围 addi $8, $4, 50 sub $1, $7, $8 lui $3, 0x0 //正确写法 ori $3, 0Xfde8 addi $8, $4, 50 sub $1, $7, $8
为什么指令必须支持不同长度的操作数:因为高级语言中的数据类型有char,short,int,long,……等,故需要存取不同长度的操作数;
指令中操作数长度由什么决定:由不同的操作码指定
示例
//A是100个字的数组(32位),g在$1, h在$2, A基址在$3
g = h + A[8];
lw $4, 32($3) //注意是4*8 = 32
add $1, $2, $4
如果在一个循环体内执行:g = h + A[i]
,则能否用基址寻址方式:不行,因为循环体内指令不能变,故首地址A不变,只能把下标 i 放在变址寄存器中,每循环一次下标加1,所以,不能用基址方式而应该用变址方式
//A是100个字的数组(32位),g在$1, i在$5, A基址在$3
g = g+A[i]
过程调用的执行步骤(假定过程P调用过程Q)
MIPS中用于过程调用的指令:beq
、j
、jr
、jal
、一些伪指令
…
少量过程调用信息用寄存器传递
如果过程中用到的参数超过4个,返回值超过2个,怎么办
参数
、保存返回地址
,并用来临时存放过程中的局部变量
等。这样可以实现嵌套和递归调用程序可访问的寄存器组是所有过程共享的资源,给定时刻只能被一个过程使用 ,因此过程中使用的寄存器的值不能被另一个过程覆盖!(主调过程使用的寄存器,被调过程要么不用,要么用完之后返回前把值还回去)
MIPS的寄存器使用约定
$s0 ~$s7
的值在从被调用过程返回后还要被用,被调用者需要保留$t0 ~$t9
的值在从被调用过程返回后不需要被用(需要的话,由调用者保存) ,被调用者可以随意使用$a0~$a3
在从被调用过程返回后不需要被用(需要的话,由调用者保存在栈帧或其他寄存器中),被调用者可以随意使用$gp
的值不变$fp
用栈指针寄存器$sp-4
来初始化需在被调用过程Q中入栈保存的寄存器(称为被调用者保存)
$ra
(如果Q又调用R,则$ra
内容会被破坏,故需保存)$s0 ~$s7
(Q返后P可能还会用到,Q中用的话就被破坏,故需保存)各处理器对栈帧规定的 ”调用者保存” 和 ”被调用者保存” 的寄存器可能不同
过程调用时MIPS中栈和栈帧的变化
过程调用协议
swap函数示例
现有swap
函数如下,主函数caller
要调用它
swap(int v[ ], int k)
{
int temp;
temp = v[k];
v[k] = v[k+1];
v[k+1] = temp;
}
temp对应$t0
(局部变量),变量v 和 k分别对应$a0
和$a1
(传入参数)
根据C语言的逻辑,可以写出以下核心逻辑代码
sll $s2, $a1, 2 ; $a1=k, mulitply k by 4
addu $s2 $s2, $a0 ; address of v[k]
lw $t0, 0($s2) ; load v[k]
lw $s3, 4($s2) ; load v[k+1]
sw $s3, 0($s2) ; store v[k+1] into v[k]
sw $t0, 4($s2) ; store old v[k] into v[k+1]
分析这段程序,swap
用到了$t0
,$s2
和$s3
,所以caller
中这三个寄存器的值被破坏。根据约定,$t0
由caller
自己保护,$s2
和$s3
需要在swap
中保护
使用jal swap
指令调用swap
函数。等价于执行以下两条指令
//jal swap
$31 = PC+4 ; $31=$ra
goto swap
程序执行顺序如下
加上保护寄存器和返回指令,完整程序如下
如果swap是叶子过程,无需保存返回地址到栈中。因为$ra
的内容不会被破坏;如果将所有内部寄存器都用临时寄存器 (如$t1
等),则叶子过程swap的栈帧为空,且上述黑色指令都可去掉
嵌套调用示例
原始C程序
int i; // 全局变量 void set_array(int num) { int array[10]; // 局部变量 for (i = 0; i < 10; i ++) arrar[i] = compare (num, i); } int compare (int a, int b) { if (sub (a, b) >= 0) return 1; else return 0; } int sub (int a, int b) { return a-b; }
过程调用时的变量分配
全局变量一般分配到寄存器或R/W存储区。
该例中只有一个简单变量i
,假定分配给$s0
。无需保存和恢复!
为减少指令条数,并减少访问内存次数,在每个过程的过程体中总是先使用临时寄存器$t0~$t9
;临时寄存器不够或者某个值在调用过程返回后还需要用,就使用保存寄存器$s0~$s7
。
set_array
过程的栈帧分析
num
,没有返回参数,有一个局部数组,被调用过程为compare
,因此,其栈帧中除了保留所用的保存寄存器外,必须保留返回地址(因为set_array
不是叶过程)$fp
要看具体情况,如果确保后面都不用到$fp
,则可以不保存,但为了保证$fp
的值不被后面的过程覆盖,通常情况下,应该保存$fp
的值,并给局部数组(int array[10]
) 预留4×10=40个字节的空间。compare
返回后还需要用到数组基地址,故将其分配给$s1
。因此要用到的保存寄存器有两个:$s0
和$s1
,但只需将$s1
保存在栈帧中($s0
保存全局变量i
不用保护),另外加上返回地址$ra
(因为已经保存了前一个函数的返回地址),帧指针$fp
(因为已经保存了前一个栈帧的尾地址)、局部数组,其栈帧空间最少为3×4+40=52B
。compare
过程的栈帧分析
a
和b
,仅一个返回参数,没有局部变量,被调用过程为sub
。 过程体中没用到保存寄存器,所以,其栈帧中只需保留返回地址$ra
和$fp
的值sub
过程的栈帧分析:叶子过程,其栈帧为空
栈的变化示意图
判断等于
//i, j, f, g, h, 分别存在 $s1, $s2, $s3, $s4, $s5
if (i == j)
f = g+h ;
else
f = g-h ;
//翻译为汇编
bne $s1, $s2, else //与C语句相反, i!=j, jump to else
add $s3, $s4, $s5
j exit //jump to exit
else: sub $s3, $s4, $s5
exit:
Loop循环
//g, h, i, j ~ $1, $2, $3, $4 and base address of array is in $5
//数组元素为int类型,sizeof(int)=4
Loop: g = g +A[i];
i = i+ j;
if (i != h) go to Loop:
//翻译为汇编
Loop: add $7, $3, $3 //i*2,加法快
add $7, $7, $7 //i*4, 得到偏移量,也可用移位
add $7, $7, $5 //加上数组基地址
lw $6, 0($7) // $6=A[i]
add $1, $1, $6 //g= g+A[i]
add $3, $3, $4 //i = i+j;
bne $3, $2, Loop //程序员不必计算分支指令的地址,而只要用标号即可!汇编 器完成地址计算
bne $3,$2,Loop
怎么翻译机器码。注意imm16
的值一定是相对下一条指令说的Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。