news 2026/9/22 9:30:21

(学习笔记)3.7 过程(3.7.4 循环)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(学习笔记)3.7 过程(3.7.4 循环)

文章目录

  • 线索栏
  • 笔记栏
    • 1. 循环的机器级实现基础
    • 2. do-while循环:基础模式
    • 3. while循环的两种翻译策略
    • 4. for循环的实现
    • 5. 逆向工程循环的通用策略(“旁注”核心)
    • 6.练习题
      • 1.练习题3.22
      • 2.练习题3.23 (dw_loop)
      • 3.练习题3.24
      • 4.练习题3.25
      • 5.练习题3.26 (fun_a)
      • 6.练习题3.27
      • 7.练习题3.28 (fun_b)
      • 8.练习题3.29 (for循环中的continue)
  • 总结栏

线索栏

  1. 核心机制:高级语言(C)的循环结构在机器级是如何实现的?汇编语言有对应的“循环指令”吗?
  2. 基础模式:do-while循环为什么被视为实现循环的“基础模式”?它的通用“goto代码”模板是什么?
  3. while循环的两种翻译策略:GCC 将while循环翻译为机器代码的哪两种主要策略?(“跳转到中间”和“guarded-do”)它们分别在什么优化级别下使用?核心区别是什么?
  4. for循环的本质:for循环在行为上等价于哪种结构?GCC 是如何为 for循环生成代码的?
  5. 编译器优化:在 guarded-do策略中,编译器如何优化循环的测试条件?(以 fact_while中 n>1被优化为 n!=1为例)
  6. 逆向工程心法:给定一段实现循环的汇编代码,如何系统地逆向推导出原始的C语言循环结构?关键步骤是什么?(“旁注”中的策略)
  7. 特殊案例:当 for循环体包含 continue语句时,将其直接转换为while循环的简单规则为什么会出错?应如何正确处理?(练习题3.29)

笔记栏

1. 循环的机器级实现基础

(1)无专用指令:汇编语言中没有与 do-while、while、for直接对应的指令。
(2)实现机制:通过条件测试和跳转指令的组合来实现。GCC 主要基于两种基本循环模式生成代码。

2. do-while循环:基础模式

(1)通用形式:do { body-statement } while (test-expr);
(2)特性:循环体至少执行一次。
(3)底层 goto 代码模板:

loop:body-statement t=test-expr;if(t)gotoloop;

(4)示例:图3-19的阶乘函数 fact_do。其汇编代码中,条件跳转指令 jg是实现循环的关键。

3. while循环的两种翻译策略

while循环在首次执行循环体前会测试条件,其翻译需要处理初始检查。

A. 跳转到中间 (Jump to Middle)

(1)常用优化等级:-Og(调试优化级别)
(2)Goto代码模板:

gototest;// 1. 初始时跳转到测试部分loop:// 2. 循环体标签body-statement test:// 3. 测试部分标签t=test-expr;if(t)gotoloop;// 4. 条件为真,跳回循环体

(3)特点:逻辑清晰,但多一次无条件跳转。图3-20的 fact_while采用此策略。

B. guarded-do (有保护的do)

(1)常用优化等级:-O1及以上
(2)Goto代码模板:

t=test-expr;if(!t)// 1. 初始测试:若条件为假,直接跳过整个循环gotodone;loop:// 2. 循环体(本质是一个 do-while 结构)body-statement t=test-expr;if(t)// 3. 循环条件测试gotoloop;done:

(3)特点与优化:用条件分支“保护”循环入口。循环体本身是高效的 do-while结构。编译器常能优化测试条件。
(4)优化示例:在图3-21的 fact_while中,循环测试从C代码的 n > 1优化为汇编的 n != 1。因为编译器知道,进入循环时 n > 1已成立,且每次 n减1,所以 n != 1等价于 n > 1。

4. for循环的实现

(1)行为等价:除了 continue语句的特殊情况(见练习题3.29),for循环在行为上严格等价于以下 while循环:

init-expr;while(test-expr){body-statement update-expr;}

(2)代码生成:GCC 首先将 for循环转换为等价的 while循环,然后根据优化等级,应用上述的“跳转到中间”或“guarded-do”策略来生成最终的汇编代码。
(3)示例:fact_for函数。其 for循环可转换为 while循环,再用“跳转到中间”策略翻译。

5. 逆向工程循环的通用策略(“旁注”核心)

理解汇编循环的关键是建立程序值与寄存器的映射关系:

(1)初始化:循环开始前,哪些寄存器被初始化?对应哪些程序变量?
(2)循环体:在循环内部,哪些寄存器的值被如何修改?
(3)条件测试:循环结束条件测试了哪些寄存器?使用什么比较和跳转指令?
(4)后续使用:循环结束后,哪些寄存器的值被如何使用(如作为返回值)?

6.练习题

1.练习题3.22


2.练习题3.23 (dw_loop)

A. 寄存器映射:x在 %rax(后被修改并返回),y(xx) 在 %rcx,n(2x) 在 %rdx。

B. 指针优化:尽管C代码中有指针 p指向 x,但编译器识别到 p始终指向本地变量 x,因此消除了间接引用。对 x的更新(x += y和 (*p)++)被合并,直接通过对寄存器 %rax(存放 x)的运算实现。

3.练习题3.24


4.练习题3.25


5.练习题3.26 (fun_a)

A. 循环翻译方法:跳转到中间(初始有 jmp .L5)。

B. C代码:while (x != 0) { val ^= x; x >>= 1; }返回 val & 1。

C. 功能:计算参数 x的二进制表示中所有比特位的奇偶校验(异或和的最低位)。返回1表示有奇数个1,0表示偶数个1。

6.练习题3.27


7.练习题3.28 (fun_b)

B. 无初始测试的原因:这是一个 for循环,且循环次数固定(64次)。编译器将其翻译成了一个 do-while风格的循环(实际是 guarded-do但保护条件恒真),因为已知至少要执行64次。循环变量 i用 %rdx(初始64)充当,每次减1,直到为0。

8.练习题3.29 (for循环中的continue)

A. 简单转换的问题:若直接将示例 for循环套用 while转换规则,continue会跳转到 update-expr(i++),这是正确的。但转换后的 while循环中,continue必须被特殊处理,使其能跳转到 i++,而不是跳过 i++直接进行条件测试。

B. 正确的 goto替换:需要在 while循环体内,用 goto update;模拟 continue,并添加一个 update:标签指向 i++;语句。


总结栏

本节系统揭示了高级语言循环结构到机器级条件跳转的编译映射,是理解程序控制流的关键。

  1. 统一于条件跳转:所有循环(do-while、while、for)最终都通过条件测试+跳转实现。do-while是最直接的基础映射。
  2. while 的两种策略:体现了编译器在代码清晰度与执行效率间的权衡。
    (1)跳转到中间​ (-Og):逻辑简单,适合调试。
    (2)guarded-do​ (-O1+):用一次条件分支保护循环,将循环体优化为高效的 do-while模式,并能进行条件优化(如 n>1到 n!=1)。
  3. for 循环的转换:for循环首先在逻辑上被“展平”为等价的while循环(初始化在前,更新在体后),再应用上述翻译策略。continue语句是此转换的陷阱,需特殊处理以保证更新表达式执行。
  4. 逆向工程心法:破解循环汇编的秘诀是 “追踪数据流”——弄清每个寄存器在循环前、中、后的角色(存放哪个变量、如何变化、如何测试)。结合goto代码模板,能有效重建高级逻辑。
  5. 设计启示:循环的编译是编译器优化的重点。策略的选择和微优化(如改变测试条件)反映了在代码大小、指令效率、分支预测友好性之间的精细权衡。理解这些,对编写高性能循环和进行底层调试至关重要。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 6:03:16

Stable-Diffusion-V1-5 快速入门:GitHub源码拉取与自定义模型加载指南

Stable-Diffusion-V1-5 快速入门:GitHub源码拉取与自定义模型加载指南 你是不是已经用上了别人打包好的Stable Diffusion WebUI,但总感觉少了点什么?看到GitHub上那些炫酷的新功能、新插件,或者想试试别人分享的“炼丹”成果——…

作者头像 李华
网站建设 2026/9/23 6:03:17

洁净车间压缩空气检测全攻略:从露点到浮游菌的5个关键指标解析

洁净车间压缩空气检测全攻略:从露点到浮游菌的5个关键指标解析 在制药、电子制造、医疗器械等高精度生产领域,压缩空气被称为"第四大公用介质",其质量直接影响产品合格率与生产线稳定性。某国际药企曾因压缩空气含油量超标导致整批…

作者头像 李华
网站建设 2026/9/23 6:03:17

手把手教你给CH32V307VCT6移植FatFS:SD卡读写与文件管理实战(附源码)

CH32V307VCT6实战:从零构建FatFS文件系统与SD卡高效管理 在嵌入式开发中,文件系统管理一直是提升设备数据存储能力的关键技术。对于使用RISC-V架构CH32V307VCT6的开发者和爱好者来说,如何快速实现SD卡的高效读写与文件管理,是项目…

作者头像 李华
网站建设 2026/9/23 6:03:20

Excel插件实战:5分钟搞定高斯坐标转经纬度(附小O地图详细配置)

Excel高效办公:高斯坐标转经纬度的专业解决方案 在数据驱动的现代办公环境中,地理信息处理已成为市场分析、物流规划和客户管理等诸多领域的必备技能。许多非GIS专业的办公人员常常需要处理各类空间数据,却苦于缺乏专业工具和知识。本文将详细…

作者头像 李华
网站建设 2026/9/23 6:03:20

计算机二级C+三级嵌入式双考亲测:这些时间分配陷阱你一定要避开

计算机二级C三级嵌入式双考实战指南:高效备考策略与避坑手册 当屏幕上的成绩查询页面同时显示"二级C语言:合格"和"三级嵌入式:优秀"时,我长舒了一口气——这场历时两个月的双线作战终于画上圆满句号。作为同时…

作者头像 李华