数据格式
C声明 | 汇编后缀 | 大小(byte) |
---|---|---|
char | b | 1 |
short | w | 2 |
int | l | 4 |
long | q | 8 |
char* | q | 8 |
float | s | 4 |
double | l | 8 |
操作数指示符
类型 | 格式 | 操作数值 |
---|---|---|
立即数寻址 | $ Imm | $Imm$ |
寄存器寻址 | $r_a$ | R[$r_a$],R[]表示引用[]内寄存器内的值 |
存储器绝对寻址 | $Imm$ | M[$Imm$],$M_b$[]表示从[]中的地址开始引用内存中的值 |
存储器间接寻址 | ($r_a$) | $M[R[r_a]]$ |
基址+偏移量寻址 | $Imm(r_b)$ | $M[Imm+R[r_b]]$ |
存储器变址寻址 | $(r_b,r_i)$ | $M[R[r_b]+R[r_i]]$ |
存储器变址寻址 | $Imm(r_b,r_i)$ | $M[Imm+R[r_b]+R[r_i]]$ |
比例变址寻址 | $(,r_i,s)$ | $M[R[r_i]\cdot s]$ |
比例变址寻址 | $Imm(,r_i,s)$ | $M[Imm+R[r_i]\cdot s]$ |
比例变址寻址 | $(r_b,r_i,s)$ | $M[R[r_b]+R[r_i]\cdot s]$ |
比例变址寻址 | $Imm(r_b,r_i,s)$ | $M[Imm+R[r_b]+R[r_i]\cdot s]$ |
数据传输
mov(b,w,l,q)S,D
:D$\rightarrow$S
movabsq I,R
:I$\rightarrow$R,传送绝对的四字
movz
把目的中剩余字节用0填充
mozs
把目的中剩余字节用符号填充
cltq
%rax$\leftarrow$符号扩展%eax
栈是向下生长的
pushq S
|R[%rsp]$\leftarrow$R[%rsp]-8;M[R[%res]]$\leftarrow$S
popq D
|D$\leftarrow$M[R[%rsp]];R[%rsp]$\leftarrow$R[%rsp]+8
算数和逻辑操作
leaq S,D
|D$\leftarrow$&S
inc D
dec D
neg D
not D
add S,D
sub S,D
mul S,D
imul S,D
xor S,D
or S,D
and S,D
sal k,D
|D$\leftarrow$D<<k
shl l,D
|D$\leftarrow$D<<k
sar k,D
|D$\leftarrow$D$>>_A$k,A:Algorithm
shr k,D
|D$\leftarrow$D$>>_L$k,L:Logic
16byte运算
指令 | 效果 |
---|---|
imultq S |
R[%rdx]:R[%rax]$\leftarrow$S*R[%rax] |
multq S |
R[%rdx]:R[%rax]$\leftarrow$S*R[%rax] |
cqto |
R[%rdx]:R[%rax]$\leftarrow$符号扩展R[%rax] |
idivq S |
R[%rdx]$\leftarrow$R[%rdx]:R[%rax] mod S |
R[%rax]$\leftarrow$R[%rdx]:R[%rax] /S | |
divq S |
R[%rdx]$\leftarrow$R[%rdx]:R[%rax] mod S |
R[%rax]$\leftarrow$R[%rdx]:R[%rax] /S |
控制
条件码
CF:进位标志
ZF:零位标志
SF:符号标志
OF:溢出标志
xor $\rightarrow$ CF=OF=0
s_r,s_l$\rightarrow$CF=最后被移出的位
cmp S1,S2 | S2-S1
,不改变寄存器,若=0,ZF=1
test S1,S2 | S2&S1
,不改变寄存器
访问条件码
指令 | 同义名 | 效果 | 设置条件 |
---|---|---|---|
sete D |
setz |
D$\leftarrow$ZF | 相等/零 |
setne D |
setnz |
D$\leftarrow$~ZF | 不等/非零 |
sets D |
D$\leftarrow$SF | negetive | |
setns D |
D$\leftarrow$~SF | nonegetive | |
setg D |
setnle |
D$\leftarrow$~(SF^OF)&~ZF |
$>_A$ |
setge D |
setnl |
D$\leftarrow$~(SF^OF) | $>=_A$ |
setl D |
setnge |
D$\leftarrow$SF^OF | $<_A$ |
setle D |
setng |
D$\leftarrow$(SF^OF)|ZF | $<=_A$ |
seta D |
setnbe |
D$\leftarrow$~CF&~ZF | $>_U$ |
setae D |
setnb |
D$\leftarrow$~CF | $>=_U$ |
setb D |
setnae |
D$\leftarrow$CF | $<_U$ |
setbe D |
setna |
D$\leftarrow$CF|ZF | $<=_U$ |
跳转
指令 | 同义名 | 跳转条件 | 描述 |
---|---|---|---|
jmp Label |
1 | 直接跳转 | |
jmp *Operand |
1 | 间接跳转 | |
je Label |
jz |
ZF | equal/zero |
jne Label |
jnz |
~ZF | neq/nzero |
js Label |
SF | neg | |
jns Label |
~SF | noneg | |
jg Label |
jnle |
~(SF^OF)&~ZF | $>_A$ |
jge Label |
jnl |
~(SF^OF) | $>=_A$ |
jl Label |
jnge |
SF^OF | $<_A$ |
jle Label |
jng |
(SF^OF)|ZF | $<=_A$ |
ja Label |
jnbe |
~CF&~ZF | $>_U$ |
jae Label |
jnb |
~CF | $>=_U$ |
jb Label |
jnae |
CF | $<_U$ |
jbe Label |
jna |
CF|ZF | $<=_U$ |
条件传送
cmov
+x
,x为条件后缀
后缀 | 条件 | 描述 |
---|---|---|
e |
ZF | eq,0 |
ne |
~ZF | neq,not 0 |
s |
SF | sub,neg |
ns |
~SF | non-neg |
g |
~(SF^OF)&~ZF | >a |
ge |
~(SF^OF) | >=a |
l |
SF^OF | < a |
le |
SF^OF | ZF | <=a |
a |
~CF&~ZF | >u |
ae |
~CF | >=u |
b |
CF | < u |
be |
CF|ZF | <=u |
条件控制实现条件分支if-else
:1
2
3
4
5
6
7 cmp ;条件判断
jmpx .L2 ;条件跳转
;if代码块
ret
.L2:
;else代码块
ret
条件传送实现条件分支
(条件控制预测错误在现代多级流水的机器上会产生大量开销,可能会非常低效)
if-else
:1
2
3
4
5
6
7
8long abs(long x,long y){
long result;
if(x < y)
result=y-x;
else
result=x-y;
return result;
}1
2
3
4
5
6
7
8absdiff:
movq %rsi,%rax
subq %rdi,%rax
movq %rdi,%rdx
subq %rsi,%rdx
cmpq %rsi,%rdi
cmovge %rdx,%rax
ret
循环
do-while
:1
2
3
4.L2:
;do something
cmp
jmpx .L2
while
:
jump to middle:1
2
3
4
5
6
7 jmp .L3
.L2:
;do sth
.L3:
cmp
jmpx .L2
ret
guarded-do(often be used when -O1 is opened):1
2
3
4
5
6
7
8 cpm
jmpx .L3
.L2:
;do sth
cmp
jmpx .L2
.L3:
ret
for
:1
2
3
4
5
6
7
8
9
10for(init-expr;test-expr;update-expr)
{
body-statement;
//等价于
init-expr;
while(test-expr)
{
body-statement;
update-expr;
}
switch
语句
使用跳转表实现:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22void switch_eg(long x, long n, long *dest)
{
long val = x;
switch (n)
{
case 100:
val *= 13;
break;
case 102:
val += 10; /* Fall through */
case 103:
val += 11;
break;
case 104:
case 106:
val *= val;
break;
default:
val = 0;
}
*dest = val;
}
等价于
1 | switch_eg: |
跳转表用如下声明表示:1
2
3
4
5
6
7
8
9
10
11;read-only-data .rodata
8 ;Align address to multiple of 8
.L4:
;Case 100: loc_A .L3
;Case 101: loc_def .L8
;Case 102: loc_B .L5
;Case 103: loc_C .L6
;Case 104: loc_D .L7
;Case 105: loc_def .L8
;Case 106: loc_D .L7
;这七个“四”字(8 byte)与起始地址.L4实际上构成了一个数组,这就是跳转表