x86 汇编入门(04):循环与条件跳转
高级语言里写 for (i = 1; i <= 10; i++) 一行搞定。汇编里没有 for,只有比较 + 跳转。这一篇用 04_loop.asm 打印 1 到 10,把循环拆成你能看见的每一步。
这是「x86 汇编入门」系列的第 4 篇。上一篇实现了算术和数字打印。这一篇通过
04_loop.asm,学习条件跳转指令和循环结构的汇编写法。
一、比较与跳转
cmp a, b 做减法但不保存结果,只设置 CPU 标志位。然后根据标志位跳转:
| 指令 | 条件 |
|---|---|
je |
相等 (ZF=1) |
jne |
不相等 |
jl |
小于(有符号) |
jle |
小于等于 |
jg |
大于 |
jge |
大于等于 |
jmp |
无条件跳转 |
二、用跳转拼出循环
04_loop.asm 的逻辑等价于:
1 | for (int i = 1; i <= 10; i++) { |
汇编实现:
1 | mov r12, 1 ; 计数器从 1 开始 |
三个要素一目了然:初始化(mov r12, 1)、条件判断(cmp + jg)、更新与回跳(inc + jmp)。
三、为什么计数器用 r12?
前面提过:syscall 会修改 rax、rcx、r11。循环里每次打印都要调 sys_write,如果计数器放在 rcx,一轮下来值就乱了。
callee-saved 寄存器(rbx、rbp、r12–r15)在系统调用前后保持不变,适合当循环变量。
四、运行输出
1 | make |
1 | 当前数字: 1 |
五、和高级语言循环对照
| C / Python | 汇编 |
|---|---|
i = 1 |
mov r12, 1 |
i <= 10 |
cmp r12, 10 + jg .loop_end |
i++ |
inc r12 |
| 回到循环头 | jmp .loop_start |
没有花指令,就是标签和跳转。理解这一点,以后看编译器生成的汇编会轻松很多。
六、小结
本篇要点:
cmp+ 条件跳转实现分支jmp实现循环回跳- 循环计数器优先用 callee-saved 寄存器
- 复用
print_number打印当前数字
x86 汇编入门系列第 4 篇完。下一篇进入函数调用——
call/ret、栈帧,以及用递归算阶乘。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 WALL-E`s Blog!







