第三章 程序的机器级表示
条件分支
-
用条件转移实现条件分支
在现代处理器上会非常低效,因为处理器通过使用流水线来获得高性能,要求能够实现确定执行的指令序列。当机器遇到条件跳转时只有当分支条件求值完成才能决定走哪条分支,处理器会采用分支预测逻辑来猜测每条跳转指令是否执行,当预测错误时会严重降低性能
-
用条件传送来实现条件分支
计算一个条件操作的两种结果,然后根据条件是否满足从中选取一个
C
//计算两个数的差的绝对值 //使用条件转移 long cmowdiff (long x, long y){ long result; if(x < y) result = y - x; else result = x - y; return result; } //使用条件传送 long cmowdiff (long x, long y){ long rval = y - x; long eval = x - y; long ntest = x >= y; if(ntest) rval = eval; return rval; }
浮点代码
浮点代码使用的寄存器是ymm0~ymm15
,可以保存32
字节,其低16
字节是xmm
寄存器,浮点函数的
xmm寄存器用来向函数传递和返回浮点数,函数使用xmm0返回浮点值
数据格式
数据类型 | 术语 | 汇编代码 | 大小 |
---|---|---|---|
字节 | byte | b | 1字节 8位 |
字 | word | w | 2字节 16位 |
双字 | double words | l | 4字节 32位 |
四字 | quad words | q | 8字节 64位 |
汇编指令
none
lea 加载有效地址
inc 加1
dec 减1
neg 取负
sal 左移
sar 算数右移
shr 逻辑右移
mul 乘
cqto 转换为8字
div 除
cmp 比较
test 测试
set 将一个字节设置为0或1
CF 进位标志,检查无符号操作的溢出
ZF 零标志
SF 符号标志
OF 溢出标志,补码的正/负溢出
过程
形式包括:函数,方法,子例程,处理函数
栈帧:存储空间超出寄存器能够存放的大小时就会在栈上分配空间,这个部分成为过程的栈帧,栈指针是rsp
,帧指针是rbp
GDB
none
kill 停止程序
delete 删除断点
info frame 有关当前栈帧的信息
info registers 所有寄存器值
对抗缓冲区溢出攻击
ASLR
:通过在程序开始时分配一段随机大小的空间而不使用,使得后续栈位置发生变化。可以通过在攻击代码前插入nop
滑过随机大小的序列
NX
:限制可执行代码区域,堆栈不可执行
canary
:检测缓冲区越界,可以使用-fno-stack-protector
关闭canary
保护