0%

CSAPP-Ch3笔记

数据格式

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
8
long 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
8
absdiff:
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
10
for(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
22
void 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
switch_eg:
subq $100, %rsi
cmpq $6,%rsi
ja .L8
jmp *.L4(,%rsi,8) ;Goto *jt[index]. '*' indicating an indirect jump
.L3:
leaq (%rdi,%rdi,2), %rax
leaq (%rdi,%rax,4), %rdi
jmp .L2
.L5:
addq $10, %rdi
.L6:
addq $11, %rdi
jmp .L2
.L7:
imulq %rdi, %rdi
jmp .L2
.L8:
movl $0, %edi
.L2:
movq %rdi, (%rdx)
ret

跳转表用如下声明表示:

1
2
3
4
5
6
7
8
9
10
11
    .section    .rodata     ;read-only-data
.align 8 ;Align address to multiple of 8
.L4:
.quad .L3 ;Case 100: loc_A
.quad .L8 ;Case 101: loc_def
.quad .L5 ;Case 102: loc_B
.quad .L6 ;Case 103: loc_C
.quad .L7 ;Case 104: loc_D
.quad .L8 ;Case 105: loc_def
.quad .L7 ;Case 106: loc_D
;这七个“四”字(8 byte)与起始地址.L4实际上构成了一个数组,这就是跳转表