除法——除基取余法
乘法——乘基取整法
UMin = 0 \\ UMax = 2^w - 1 \\
TMin = -2^{w-1} \\ TMax = 2^{w-1} - 1 \\
位模式不变、数值可能改变(按不同编码规则重新解读)
隐式转换
符号扩展
整数截断
\begin{array}{c} X' = X \mod 2^k \end{array}
\begin{array}{c} X' = (signed)((unsigned)X \mod 2^k) \end{array}
1. 无符号数加法 \begin{array}{c} UAdd_w(x,y) = (x + y) \mod 2^w = \begin{cases} x + y & x + y \lt 2^w \\ x + y - 2^w & x+y \geq 2^w \\ \end{cases} \end{array}
2. 有符号数加法 \begin{array}{c} TAdd_w(x,y) = (signed)UAdd_w((unsigned)x,(unsigned)y) \\ = \begin{cases} x + y - 2^w & TMax_w \lt x + y \ \text{正溢出} \\ x + y & TMin_w \leq x + y \leq TMax_w \ \text{正常} \\ x + y + 2^w & x + y \lt TMin_w \ \text{负溢出} \end{cases} \end{array}
【注】CPU 其实并不知道操作的是有/无符号数,CPU 所做的便是将两个 w 位的二进制数 x、y 相加并将结果的进位 w+1 位去掉(即只保留结果的后 w 位)。
\begin{array}{c} UMult_w(x,y) = (x \cdot y) \mod 2^w \\ TMult_w(x,y) = (signed)UMult_w((unsigned)x,(unsigned)y) \\ \end{array}
\begin{array}{c} TDiv(x,y) = \begin{cases} \lfloor {x \over y} \rfloor & x \cdot y \gt 0 \\ 0 & x = 0 \\ \text{错误} & y = 0 \\ \lceil {x \over y} \rceil & x \cdot y \lt 0 \\ \end{cases} \end{array}
1. 向上舍入转为向下舍入: \begin{array}{c} \lceil {x \over y} \rceil = \lfloor {x + y - 1 \over y} \rfloor \end{array}
2. 使用移位表示 2 的整数幂除法 \begin{array}{c} {x \over 2^k} = (x \lt 0 \ ? \ x+(1 \ll k)-1 : x) \gg k \end{array}
参见「浮点数」 。
此以 x86-64 指令集的 AT&T 格式为例。x86_64 指令长度 1 到 15 个字节不等。
x86 汇编语言有两种语法:AT&T 、Intel 。其中前者用于 Unix 系统家族,后者用于 DOS 和 Windows 家族。这两种语法格式的区别如下:
1. AT&T 格式指令后缀
【注】x86_64 规定:任何为寄存器生成 32 位值的指令都会把该寄存器的高位部分置 0 。即生成 1 字节和 2 字节数字的指令会保持剩下的字节不变,生成 4 字节数字的指令会把高位 4 个字节置 0 。
【注】cltq 指令用于将 %eax 可符号扩展为 %rax,其不需要任何操作数。
【注】leaq 指令不设置条件码,因为它是用于进行地址计算的。对于逻辑操作,进位标志和溢出标志会设置位0。对于 INC 和 DEC 指令,不会设置 CF 位,因为该二者主要用于循环变量的加减,不修改 CF 位是考虑到循环中有可能进行高精度大数运算;而且 CF 位可以根据 ZF 位来判断,INC 且当前指令 ZF,则说明当前指令产生了进位;DEC 且上一条指令 ZF,则说明当前指令产生了借位。
【注】cqto 指令不需要操作数,隐含读出 %rax 的符号位并将它复制到 %rdx 的所有位。
【注】compq 和 testq 指令仅将计算结果用于设置条件码,而并不改变操作数。
函数传参使用寄存器原则
【重点】跳转表 跳转表的实现是 swtich 性能优于 if-else 语句的原因。跳转表通过将需要执行的分支地址组合成一个数组,然后根据 switch 中的值用于该数组的索引下标,从而实现跳转只需要使用 jmp 指令的间接跳转到相应的分支。
对齐要求
对抗缓冲区溢出攻击
高速缓存的结构可以用元组 (S,E,B,m) 来描述。高速缓存的大小/容量 C 指的是所有块的大小的和,标记位和有效位不包括在内,故
\begin{array}{c} C = S \times E \times B \end{array}
其中,SSS 为组数、EEE 为组相连路数、BBB 为每个缓存块的字节数。
缓冲不命中