CSAPP:程序的机器级表示-3
本文最后更新于:2022年9月4日 下午
思考两个问题:
- 控制结构相对应的机器语言的控制结构(汇编语言)
- C语言实现的分支、循环、开关等操作,在底层的机器语言是如何实现的?
条件码的隐式赋值
几种标志寄存器
- CF 进位标志位(Carry Flag, 无符号数)
- SF 符号标志识位(Sign Flag, 有符号数)
- ZF 零标志位 ( Zero Flag )
- OF 溢出标志位( Overflow Flag , 有符号数)
add指令
addq Src,Dest 隐含了:t = a+b
- CF=1
- 进位
- 当两数相加产生进位/两数相减产生进位的情况下CF=1
- 127+127、1-2
- 把两个数当做无符号数,相加结果是否有进位?若有进位,则CF=1
- ZF=1
- 运算结果为0
- SF=1
- 将t看做是有符号数,t<0的情况下,SF=1
- 运算结果可以看做是有符号数,也可以看做是无符号数,因此具有两种含义
- 假设运算结果为10000001,可以看做是无符号数+129,也可以看做是有符号数-1
- PF
- 奇偶标志位,如果运算结果的二进制表示中1的个数为偶数,PF=1,否则为0
- OF=1
- 有符号数(补码)溢出的情况
- 把两个数当做有符号数,相加结果是否有溢出?
- (a>0 && b>0 && t<0) || (a<0 && b<0 && t>=0)
cmp
cmpq Src1, Src2会计算Src2-Src1的值并改写条件码,但是不会改变这两个操作数
- 对标志寄存器值的判断依据与上面add指令相似
- t=Src2-Src1
跳转指令
C语言到汇编语言的转换
if else 语句
1 |
|
转换为如下goto语句:
1 |
|
转换为如下汇编:
1 |
|
对于三目运算符
1 |
|
也可表示为ifelse语句,从而改写为汇编语句
循环结构
1 |
|
- 计算x的二进制表示中有多少个1
转化为goto语句:
1 |
|
转换为如下汇编:
1 |
|
for循环转化为while的通用版本:
1 |
|
do-while循环与while循环相似。两者唯一的分别:do-while循环将先会执行一次循环内的代码,再去判断循环条件。所以无论循环条件是否满足,do-while循环内的代码至少会执行一次。因此,do-while循环属于后测循环(post-test loop)。
do-while循环转化为goto的通用版本:
1 |
|
switch结构
1 |
|
1 |
|
- jmp到跳转表
- 跳转表是一个数组,存储了不同case入口处的地址
- 由于每个存储地址的指针是8个字节,因此比例因子为8
- 基址为.L4,跳转的x存储在%rdi,则需要跳转到.L4 + x*8处,也即是jmp *.L4(,%rdi,8)
CSAPP:程序的机器级表示-3
http://gls.show/p/a9307f29/