分类: LINUX
2010-05-28 09:46:51
存储/加载指令
1 整数存储指令
整数存储指令如表1所示。
表1 整数存储指令
名称 |
助记符 |
语法格式 |
字节存储(偏移地址寻址) |
stb |
rS, d(rA) |
字节存储(寄存器寻址) |
stbx |
rS, rA, rB |
记录有效地址的字节存储(偏移地址寻址) |
stbu |
rS, d(rA) |
记录有效地址的字节存储(寄存器寻址) |
stbux |
rS, rA, rB |
半字存储(偏移地址寻址) |
sth |
rS, d(rA) |
半字存储(寄存器寻址) |
sthx |
rS, rA, rB |
记录有效地址的半字存储(偏移地址寻址) |
sthu |
rS, d(rA) |
记录有效地址的半字存储(寄存器寻址) |
sthux |
rS, rA, rB |
字存储(偏移地址寻址) |
stw |
rS, d(rA) |
字存储(寄存器寻址) |
stwx |
rS, rA, rB |
记录有效地址的字存储(偏移地址寻址) |
stwu |
rS, d(rA) |
记录有效地址的字存储(寄存器寻址) |
stwux |
rS, rA, rB |
st(ore)
** 的指令都是将寄存器中值存储到存储器(内存等)
(1)
stb rS,d(rA)
有效地址(EffectAddr)为rA的内容加d,rS的低8位 内容存储到有效地址为EA的 存储器中。
(2)
stbx rS,rA,rB
有效地址为rA的内容加上rB的内容,rS的低8位内容存储到有效地址为EA的 存储器中。
(3)
stub rS,d(rA)
有效地址EA=(rA)+d,rS的低8位 内容存储到有效地址为EA的存储器中。rA=EA,如果rA=0,则 指令无效。
(4)
stbux rS,rA,rB
有效地址EA=(rA)+(rB),rS的低8位 内容存储到有效地址为EA的存储器中,rA=EA,如果rA=0,则 指令无效。
(5)
sth rS,d(rA)
有效地址EA=(rA)+d,rS的低16位 内容存储到有效地址为EA的存储器中。
(6)
sthu rS,d(rA)
有效地址EA=(rA)+d,rS的低16位 内容存储到有效地址为EA的存储器中。rA=EA,如果rA=0,则 指令无效。
(7)
stw rS,d(rA)
有效地址EA=(rA)+d,rS的32位 内容存储到有效地址为EA的存储器中。
(8)
stwu rS,d(rA)
有效地址EA=(rA)+d,rS的32位 内容存储到有效地址为EA的存储器中,rA=EA,如果rA=0,则 指令无效。
(9)
stwux rS,rA,rB
有效地址EA=(rA)+(rB),rS的32位 内容存储到有效地址为EA的存储器中。rA=EA,如果rA=0,则 指令无效。
(10)字存储指令stwx(寄存器寻址)
stwx rS,rA,rB
有效地址EA=(rA)+(rB),rS的32位 内容存储到有效地址为EA的存储器中。
2、整数加载指令
整数加载指令如表2所示。
表2 整数加载指令
名称 |
助记符 |
语法格式 |
高位清零加载字节指令(偏移地址寻址) |
lbz |
rD, d(rA) |
高位清零的加载字节指令(寄存器寻址) |
lbzx |
rD, rA, rB |
高位清零的加载字节并记录有效地址指令(偏移地址寻址) |
lbzu |
rD, d(rA) |
高位清零的加载字节并记录有效地址指令(寄存器寻址) |
lbzux |
rD, rA, rB |
高位清零的加载半字指令(偏移地址寻址) |
lhz |
rD, d(rA) |
高位清零的加载半字指令(寄存器寻址) |
lhzx |
rD, rA, rB |
高位清零的加载半字并记录有效地址指令(偏移地址寻址) |
lhzu |
rD, d(rA) |
高位清零的加载半字并记录有效地址指令(寄存器寻址) |
lhzux |
rD, rA, rB |
加载半字指令(偏移地址寻址) |
lha |
rD, d(rA) |
加载半字指令(寄存器寻址) |
lhax |
rD, rA, rB |
加载半字并记录有效地址指令(偏移地址寻址) |
lhau |
rD, d(rA) |
加载半字并记录有效地址指令(寄存器寻址) |
lhaux |
rD, rA, rB |
加载字指令(偏移地址寻址) |
lwz |
rD, d(rA) |
加载字指令(寄存器寻址) |
lwzx |
rD, rA, rB |
加载字并记录有效地址指令(偏移地址寻址) |
lwzu |
rD, d(rA) |
加载字并记录有效地址指令(寄存器寻址) |
lwzux |
rD, rA, rB |
l(oad)** 指令从存储器(内存等)取数据加载到寄存器
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
(10)lhzu rD, d(rA) ;EA=(rA|0)+d。从存储器EA处 读取两个字节的数,并加载到rD的低16位。rD其他位清零。EA存入rA, 如果rA=0或 者rA=rD, 则指令格式无效。
(11)lhzux rD,rA,rB ;EA=(rA)+ (rB)。从存储器EA处读取两个字节的数,加载到rD的低16位,rD其 他位清零。EA存入rA,如果rA=0或者rA=rD,则指令格式无效。
(12)lhzx rD,rA,rB ;EA=(rA|0)+ (rB),从EA处 读取两个字节的数,并加载到rD的低16位,将rD的其他位清零。
(13)lwz rD,d(rA) ;EA=(rA|0)+d,从EA处 读取4个字节的数,并加载到rD。
(14)lwzu rD,d(rA) ;EA=(rA)+d,从EA处 读取4个字节的数,并加载到rD。rA=EA,如果rA=0或rA=rD,则指令格式无效。
(15)lwzux rD,rA,rB ;EA=(rA)+ (rB),从EA处 读取4个字节的数,并加载到rD。rA=EA,如果rA=0或rA=rD,则指令格式无效。
(16)lwzx rD,rA,rB ;EA=(rA|0)+ (rB),从EA处 读取4个字节的数,并加载到rD。
整数多字存储/加载指令
表3 整数多字存储/加载指令
名称 |
助记符 |
语法格式 |
多字加载 |
lmw |
rD,d(rA) |
多字存储 |
stmw |
rS,d(rA) |
(1)
(2)
转移指令
表4 分支控制指令
名称 |
助记符 |
语法格式 |
无条件转移 |
b( ba bl bla) |
target_addr |
条件转移 |
bc( bca bcl bcla) |
BO,BI,target_addr |
条件转移(转移目标地址由LR指出) |
bclr(bclrl) |
BO,BI |
条件转移(转移目标地址由CTR指出) |
bcctr(bcctrl) |
BO,BI |
(1)
指令的编码格式:
指令的语法格式:
b target_addr(AA=0 LK=0)
ba target_addr(AA=1 LK=0)
bl target_addr(AA=0 LK=1)
bla target_addr(AA=1 LK=1)
如果AA=0, 则转移目标地址为LI||0b00的值经符号位扩展后加上指令地址。(相对跳转)
如果AA=1, 则转移目标地址为LI||0b00的值经符号扩展后的值。(绝对地址跳转)
如果LK=1, 则转移指令下一条指令的有效地址存放到连接寄存器。
(2)
指令编码格式:
条件跳转指令皆以 bc 开头,带 3 个操作数,如:
bc BO, BI, BD
bca BO, BI, BD
bcl BO, BI, BD
bcla BO, BI, BD
后缀 a, l 的含义与 branch 类指令同。BO 指定跳转的条件,5 位;BI 指定关联的 CR 位,也是 5 位;BD
为跳转的立即数地址,16 位。
其中以 BO 的编码最为复杂(BO 从左到右编号为 0 ~ 4):
BO[0]: 为 1,则直接跳转
BO[1]: 为 1,则条件为真时,跳转。否则条件为假时,跳转
BO[2]: 为 1,则 CTR 不自动减 1
BO[3]: 为 1 时,则 CTR == 0 时跳转;为 0 时,则 CTR != 0 时跳转
BO[4]: 静态预测位,1 表示 unlikely,0 表示 likely
则常见的 BO 值:
0x14 (0b10100) 则表示无条件跳转
0x0c (0b01100) 则表示 CR 的某个位为 1 时跳转
0x04 (0b00100) 则表示 CR 的某个位为 0 时跳转
至于静态预测的策略位BO[4],
被置为 0(黄色)
或 1 (绿色) ,则其行为为:
I. 目标地址小于当前指令地址,预测为 跳转 不跳转
II. 目标地址大于当前指令地址,预测为 不跳转 跳转
III. 对于目标地址在 CTR/LR 中的条件跳转指令,一律预测为 不跳转 跳转
可以给分支指令加一个 +/- 的后缀,来简化。加 '+' 的指令,一律预测为跳转。加 '-' 的分支指令,一律预测为不跳转。
则对于 b1,后缀 '+' 会将 y 位置 0,'-' 则将 y 位置 1。
对于 b2,后缀 '+' 会将 y 位置 1,'-' 则将 y 位置 0。
对于 b3,后缀 '+' 会将 y 位置 1,'-' 则将 y 位置 0。
BI 与关联 CR 位的关系为:
32 + BI
即,若 BI 为 2,则对应于 CR[34],即为 CR0[gt] 位。
以上针对 32 位的情形,对 64 位则使用指令 bce, bcea, bcel, bcela 功能与上同。
指令语法格式:
bc BO, BI, target_addr(AA=0 LK=0)
bca BO, BI, target_addr(AA=1 LK=0)
bcl BO, BI, target_addr(AA=0 LK=1)
bcla BO, BI, target_addr(AA=1 LK=1)
BI字段表示条件寄存器CR中的位用于转移条件。BO字段操作码定义见 表5。
表5 BO字段操作码定义
BO |
说明 |
0000y |
计数器CTR减量,如果条件不成立则转 移 |
0001y |
计数器CTR减量,如果条件不成立则转 移 |
001zy |
如果条件不成立,则转移 |
0100y |
计数器CTR减量,如果条件成立则转移 |
0101y |
计数器CTR减量,如果条件成立则转移 |
011zy |
如果条件成立则转移 |
1z00y |
计数器CTR减量,如果CTR!=0, 则发生转移 |
1z01y |
计数器CTR减量,如果CTR=0, 则发生转移 |
1z1zz |
发生转移 |
注:位z表示该位可以被忽略,位y表示是不是条件转移
(2)
指令的编码格式:
指令的语法格式:
bclr BO, BI(LK=0)
bclrl BO, BI(LK=1)
BI字段表示条件寄存器CR中的位用于转移条件。
BO字段操作码定义如表5所示。
转移目标地址为LR[0-29]||0b00。
如果LK=1, 则转移指令下一条有效地址存放到连接寄存器。
(3)
指令的编码格式:
指令的语法格式:
bcctr BO, BI(LK=0)
bcctrl BO, BI(LK=1)
转移目标地址是CTR||0b00。
如果LK=1, 则转移指令下一条指令的有效地址存放到连接寄存器。
如果减量计数器(BO[2]=0),指令格式无效,则转移到目标地址。
特殊寄存器传送指令
特殊寄存器传送指令如表6所示。
表6 特殊寄存器传送指令
名称 |
助记符 |
语法格式 |
读取机器状态寄存器 |
mfmsr |
rD |
写入机器状态寄存器 |
mtmsr |
rS |
读取特殊功能寄存器 |
mfspr |
rD, SPR |
写入特殊功能寄存器 |
mtspr |
SPR, rS |
读取段寄存器 |
mfsr |
rD, SR |
写入段寄存器 |
mtsr |
SR, rS |
间接读取段寄存器 |
mfsrin |
rD, rB |
间接写入段寄存器 |
mtsrin |
rS, rB |
读取时基寄存器 |
mftb |
rD, TBR |
(1)
mfmsr rD
读取MSR的内容放入rD中,这是超级用户层指令,不影响其他寄存器。
(2)写入机器状态寄存器指令mtmsr
指令的编码格式:
指令的语法格式:
mtmsr rS
把rS的内容存入MSR中,这是超级用户指令。
(1)
指令的编码格式:
指令的语法格式:
mfspr rD,SPR
指令操作:
n<—spr[5-9]||spr[0-4]
rD<—spr(n)
特殊功能寄存器(SPR)的编码如表7所示,将SPR的 内容存入rD中。
表7 Power PC UISA SPR编码
|
spr |
|
寄存器名 |
编码n |
spr[5-9] |
spr[0-4] |
|
1 |
00000 |
00001 |
XER |
8 |
00000 |
01000 |
LR |
9 |
00000 |
01001 |
CR |
(2)
指令的编码格式:
指令的语法格式:
mtspr spr,rS
把rS的内容存入到指定的特殊功能寄存器中。
(3)
指令的编码格式:
指令的语法格式:
指令操作:
rD<—SEGREG(SR)
将段寄存器SR的内容读入rD中,这是一个超级用户层指令。
(4)
指令的编码格式:
指令的语法格式:
mtsr SR,rS
将rS中的内容读入SR,这是一个超级用户层指令。
(5)
指令的编码格式:
指令的语法格式:
mfsrin rD,rB
指令操作:
rD<—SEGREG(rB[0-3])
由rB寄存器的0~3位选取的段寄存器的内容,复制到rDzhong。这是一个超级用户层指令。
(6)
指令的编码格式:
指令的语法格式:
mtsrin rS,rB
指令操作:
SEGREG(rB[0-3])<—(rS)
将rS中的内容复制到由rB的0~3位所指定的寄存器中。这是一个超级用户层指令。
(7)
指令的编码格式:
指令的语法格式:
mftb rD,TBR
指令操作:
n<—tbr[5-9]||tbr[0-4]
if n=268 then
rD<—TBL
else if n=269 then
rD<—TBU
该指令的TBR编码如表8所示。
表8 指令mftb的TBR编 码
|
TBR |
|
寄存器名 |
访问 |
编码 |
tbr[5-9] |
tbr[0-4] |
|
|
268 |
01000 |
01100 |
TBL |
用户 |
269 |
01000 |
01101 |
TBR |
用户 |
系统调用指令
(1)
指令的编码格式:
指令的使用:
sc指令调用操作系统去执行服务程序。当控制返回到一个执行系统调用的 程序时,寄存器的内容依赖于程序提供的系统所使用的寄存器的约定。
跟在sc指令后面的有效指令地址被放在SRR0中。MSR中 的位0、5~9和16~31被放在SRR1中 对应的位置,SRR1中位1~4和10~15被设置为未定义值。当sc异常产生,异常处理程序更改MSR寄存器。异常处理程序到MSR[IP]形 成基址加0xC00偏移量形成的地址去取下一条指令。
受影响的寄存器有:
依赖于系统服务、SRR0、SRR1及MSR。
(2)
指令的编码格式:
指令操作:
MSR[16-23,25-27,30-31] <—SRR1[16-23,25-27,30-31]
NIA<—iea SRR0[0-29]||0b00
SRR1中的位0、5~9和16~31被放在MSR中 对应的位置。如果新的MSR值没有使能任何未完的操作,则在MSR的控制下,从地址SRR0[0-29]||0b00取 下一条指令。
指令的使用中受影响的寄存器为MSR。
PowerPC汇编基础篇
PowerPC正用于和曾经用于 IBM服务器, 苹果电脑,任天堂Gamecube游戏机
Gekko 芯片用在了任天堂的 GameCube 中,Xenon 则用在了 Microsoft 的 Xbox 360 中。Cell Broadband Engine 是近来崭露头角的一种体系结构,使用 PowerPC 指令,并且具有八个向量处理器。Sony PlayStation 3 将使用 Cell,考虑到 PlayStation 3 将用于广泛的多媒体应用程序,因此还使用为数众多的其他向量。
PowerPC 指令集比 POWER 处理器系列更加有用。指令集本身可以 64 位模式操作,也可以简化的 32 位模式操作。POWER5 处理器支持这两种模式,POWER5 上的 Linux 发布版支持为 32 位和 64 位 PowerPC 指令集而编译的应用程序。
PPC32 Linux和NetBSD使用 SVR4 ABI
PPC64 Linux和AIX
SVR4 ABI
1)传参数从 GPR3 开始
2)GPR3-GPR12 是容易失去的寄存器。如果需要,在调用子例程之前,必须先保存并在返回后恢复.
PowerPC 寄存器有编号,而没有名称。对于初学者来说,有时这会使人混淆,因为 tts
无法轻易地与寄存器区分开。3可以表示数值3或者寄存器 gpr3 ,或者浮点 fpr3 ,或者特殊用途的寄存器 spr3
。习惯了就好了。:)
但是,在GDB的反汇编中, 寄存器是用 r3 表示的
r0 跟stack frame有关系, 当建立stack frame时,用来保存旧的LR
r1 stack pointer
r2 toc(table of content)指针
r3 第一个参数, 返回值也放在这个寄存器
r11 常用做指针
lr 链接寄存器,它用来存放函数调用结束处的返回地址。
ctr 计数寄存器,它用来当作循环计数器,会随特定转移操作而递减。
xer 定点异常寄存器,存放整数运算操作的进位以及溢出信息。
msr 机器状态寄存器,用来配置微处理器的设定。
cr 条件寄存器,它分成8个4位字段,cr0-cr7,它反映了某个算法操作的结果并且提供条件分支的机制。
li REG, VALUE
加载寄存器 REG,数字为 VALUE
add REGA, REGB, REGC
将 REGB 与 REGC 相加,并将结果存储在 REGA 中
addi REGA, REGB, VALUE
将数字 VALUE 与 REGB 相加,并将结果存储在 REGA 中
mr REGA, REGB
将 REGB 中的值复制到 REGA 中
or REGA, REGB, REGC
对 REGB 和 REGC 执行逻辑 “或” 运算,并将结果存储在 REGA 中
ori REGA, REGB, VALUE
对 REGB 和 VALUE 执行逻辑 “或” 运算,并将结果存储在 REGA 中
and, andi, xor, xori, nand, nand, and nor
其他所有此类逻辑运算都遵循与 “or” 或 “ori” 相同的模式
ld REGA, 0(REGB)
使用 REGB 的内容作为要载入 REGA 的值的内存地址
lbz, lhz, and lwz
它们均采用相同的格式,但分别操作字节、半字和字(“z” 表示它们还会清除该寄存器中的其他内容)
b ADDRESS
跳转(或转移)到地址 ADDRESS 处的指令
bl ADDRESS
对地址 ADDRESS 的子例程调用
cmpd REGA, REGB
比较 REGA 和 REGB 的内容,并恰当地设置状态寄存器的各位
beq ADDRESS
若之前比较过的寄存器内容等同,则跳转到 ADDRESS
bne, blt, bgt, ble, and bge
它们均采用相同的形式,但分别检查不等、小于、大于、小于等于和大于等于
std REGA, 0(REGB)
使用 REGB 的地址作为保存 REGA 的值的内存地址
stb, sth, and stw
它们均采用相同的格式,但分别操作字节、半字和字
sc
对内核进行系统调用
所有计算值的指令均以第一个操作数作为目标寄存器。在所有这些 指令中,寄存器都仅用数字指定。例如,将数字 12 载入寄存器 5 的指令是 li 5, 12。我们知道,5 表示一个寄存器,12 表示数字 12,原因在于指令格式(因为li第一个操作数就是寄存器,第2个是立即数)。
在某些指令中,GPR0 只是代表数值 0,而不会去查找 GPR0 的内容。
一个最简单的例子
.globl .main
.main:
li 3, 5
blr
保存为 simple.s
用gcc来汇编连接
$gcc simple.s -o simple
$./simple
$ echo $?
5
说明上次运行的程序,返回值是5