《深入理解计算机系统》程序的机器级表示 《深入理解计算机系统》第三章“程序的机器级表示”是理解计算机如何执行高级语言程序的核心内容它主要揭示了C语言与汇编代码之间的映射关系以及处理器、内存和寄存器等硬件层面的工作机制。以下分点梳理该章节的关键知识点。1. 程序编码与数据格式机器级程序由指令组成每条指令对应一个简单的操作如加法、数据传送、跳转等。程序在内存中以字节序列形式存储处理器通过指令指针PC逐条读取并执行。数据格式包括字节1字节、字2字节、双字4字节、四字8字节和八字16字节其中八字用于支持128位操作如两个64位数相乘的结果保存在%rdx\%rdx%rdx高64位和%rax\%rax%rax低64位中。2. 访问信息与数据传送寄存器是CPU中最快的存储单元x86-64架构提供16个通用寄存器。操作数指示符分为立即数、寄存器和内存引用三类。数据传送指令如mov系列的格式为mov S, D将源操作数S移动到目的操作数D。压入栈push和弹出栈pop操作则通过栈指针%rsp\%rsp%rsp实现栈帧管理。3. 算术和逻辑操作指令集支持加载有效地址leaq、一元操作如inc、dec、二元操作如add、sub、imul等以及移位操作sal、shr等。特殊的算术操作符如imulq和idivq用于有符号乘除其中乘法产生双倍长度的结果除法需要将%rdx:\%rdx:%\%rax%rdx:作为被除数。4. 控制与条件码条件码寄存器CF、ZF、SF、OF记录算术运算的额外状态。通过cmp或test指令设置条件码然后使用条件跳转如je、jg或条件传送如cmovge实现分支控制。循环通常转换为其对应的汇编形式如do-while、while和for。switch语句则通过跳转表实现高效多路分支。5. 过程函数调用过程调用涉及运行时栈的管理。调用者使用call指令将返回地址压栈被调用者使用push保存寄存器并通过ret指令返回。参数通过寄存器如%rdi\%rdi%rdi、%rsi\%rsi%rsi等传递超出6个的参数则通过栈传递。局部变量可以存储在寄存器或栈上递归过程通过重复使用栈帧实现。6. 数组分配与指针运算数组在内存中是连续存储的。指针运算通过leaq指令高效计算地址例如a[i]等价于ai∗sizeof(element)a i*sizeof(element)ai∗sizeof(element)。嵌套数组按行优先顺序存储定长数组的访问经编译器优化后可能直接使用偏移量变长数组则需要在运行时计算。7. 异质数据结构结构体struct中的字段按声明顺序排列但存在对齐要求如4字节数据要从4的倍数地址开始。联合union的各个字段共享同一起始地址节省内存但使用时需小心。对齐规则影响结构体的大小编译器会在字段间插入填充字节以满足对齐约束。8. 缓冲区溢出与对抗技术缓冲区溢出攻击利用未检查边界的gets、strcpy等函数覆盖返回地址。对抗技术包括栈随机化地址空间布局随机化ASLR、栈破坏检测金丝雀值和限制可执行代码区域NX位。GDB调试器可用于观察机器级代码的执行过程。9. 浮点代码浮点运算使用SSE指令集寄存器为XMM16个128位寄存器。浮点传送指令如vmovss、vmovsd转换指令如cvttss2si将浮点转为整数。浮点算术操作包括vaddss、vsubss等常数通过从内存加载或使用vxorps清零生成。浮点比较通过comiss、ucomiss设置条件码实现条件分支。