10.11循环处理的实现方法
接下来,让我们继续解析汇编语言的源代码,看一下 for 循环及 if条件分支等 C 语言程序的流程控制是如何实现的 。代码清单 10-8 是将局部变量i作为循环计数器“连续进行 10 次循环的 C 语言源代码。在for 语句中,调用了不做任何处理的 MySub 函数。这里我们把代码清单10-8 转换成汇编语言,然后仅把相当于 for 处理的部分摘出来,如代码清单 10-9 所示。
C 语言的 for 语句是通过在括号中指定循环计数器的初始值(i=0)、循环的继续条件(i< 10 )、循环计数器的更新( +)这3 种形式来进行循环处理的。与此相对,在汇编语言的源代码中,循环是通过比较指令( cmp )和跳转指令 (jl) 来实现的。
下面就让我们按照代码清单 10-9 的内容的顺序来进行说明MyFunc 函数中用到的局部变量只有i,变量i请分配了 ebx 寄存器的内存空间。for 语句的括号中的 i=0; 被转换成了 xor ebx,ebx 这一处理xor 指令会对左起第一个操作数和右起第二个操作数进行 XOR 运算然后把结果存储在第一个操作数中。由于这里把第一个操作数和第二个操作数都指定为了ebx,因此就变成了对相同数值进行 XOR 运算也就是说,不管当前 ebx 寄存器的值是什么,结果肯定都是 0。虽然用mov 指令的mov ebx,0 也会得到同样的结果,但与 mov 指令相比,xor指令的处理速度更快。这里,编译器的最优化功能也会启动。
ebx 寄存器的值初始化后,会通过 call 指令调用 MySub 函数(_MySub)。从MySub 函数返回后,则会通过inc 指令对ebx 寄存器的值做加1处理。该处理就相当于 for 语句的 i+,+ 是当前数值加1的意思。
下一行的 cmp 指令是用来对第一个操作数和第二个操作数的数值进行比较的指令。cmp ebx,10 就相当于 C语言的 10 这一处理,意思是把 ebx 寄存器的数值同 10 进行比较。汇编语言中比较指令的结果,会存储在 CPU 的标志寄存器中。不过,标志寄存器的值,程序是无法直接参考的。那么,程序是怎么来判断比较结果的呢?
实际上,汇编语言中有多个跳转指令,这些跳转指令会根据标志寄存器的值来判定是否需要跳转。例如,最后一行的jl,是 jump oniess than (小于的话就跳转 )的意思。也就是说,jl short @4 的意思就是,前面运行的比较指令的结果若“小”的话就跳转到 @4 这个标签。
代码清单 10-10 是按照代码清单10-9 中汇编语言源代码的处理顺序重写的 C语言源代码(由于 C语言中无法使用 @字符开头的标签因此这里用了 L4 这个标签名 ),也是对程序实际运行过程的一个直接描述。不过看来看去还是觉得使用 for 语句的代码清单 10-8 的源代码更智能些。人们经常说“汇编语言是对 CPU 的实际运行进行直接描述的低级编程语言,C 语言是用与人类的感觉相近的表现来描述的高级编程语言”,此时,想必大家都能深切体会这句话的意思了吧。此外,代码清单 10-10 的第一行中的 i=i,意思是对i和i进行 XOR 运算,并把结果代入 i。为了和汇编语言的源代码进行同样的处理,这里把将变量i的值清0这一处理,通过对变量i和变量i进行 XOR 运算来实现了借助 i^=i,i的值就变成了 0。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· 地球OL攻略 —— 某应届生求职总结