条件跳转与循环
使用比较指令(CMP、TEST)和条件跳转指令(JMP、JE、JNE、JL、JG 等)实现决策和重复任务。
条件跳转与循环 是 CoddyKit 上的免费 Assembly Language & x86 Low-Level Systems Programming 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Assembly Language & x86 Low-Level Systems Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Assembly Language & x86 Low-Level Systems Programming 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Guiding Program Flow
Programs rarely run straight through. We need to make decisions and repeat actions. This is called control flow.
Assembly language provides special instructions to change the order in which instructions are executed. This allows your programs to be dynamic and respond to different conditions.
Think of it like a choose-your-own-adventure story: you decide which path to take next!
Always Taking the Jump
The simplest way to change program flow is with an unconditional jump using the JMP instruction. It always transfers control to a specified label.
This is like a "goto" statement in higher-level languages. The program will immediately execute instructions starting from the target label.
section .data
msg1 db "Hello!", 0xA
len1 equ $ - msg1
msg2 db "Skipped!", 0xA
len2 equ $ - msg2
msg3 db "End.", 0xA
len3 equ $ - msg3
section .text
global _start
_start:
mov rax, 1 ; syscall write
mov rdi, 1 ; stdout
mov rsi, msg1
mov rdx, len1
syscall ; Print "Hello!"
jmp skip_message ; Unconditional jump
mov rax, 1
mov rdi, 1
mov rsi, msg2
mov rdx, len2
syscall ; This part is skipped!
skip_message:
mov rax, 1
mov rdi, 1
mov rsi, msg3
mov rdx, len3
syscall ; Print "End."
mov rax, 60 ; syscall exit
mov rdi, 0
syscallMaking Comparisons (CMP)
Before we can make decisions, we need to compare values. The CMP instruction does this for us.
CMP destination, source works like SUB destination, source, but it discards the result. Instead, it only updates the CPU flags based on the comparison.
This is crucial for conditional jumps!
; Compare AX with BX
cmp ax, bx
; Compare value in memory with 10
cmp [my_var], 10
; Compare AL with 0
cmp al, 0The CPU Flags Register
After a CMP instruction (or most arithmetic/logic ops), special bits in the Flags Register are updated. These bits tell us about the result of the operation.
- ZF (Zero Flag): Set if the result was zero (or operands were equal).
- SF (Sign Flag): Set if the result was negative.
- CF (Carry Flag): Set if an unsigned overflow occurred.
- OF (Overflow Flag): Set if a signed overflow occurred.
Conditional jumps check these flags!
Jumping on Equality (JE, JNE)
Once CMP sets the flags, we can use conditional jump instructions. Two common ones are JE (Jump if Equal) and JNE (Jump if Not Equal).
JE label: Jumps if the Zero Flag (ZF) is set (meaning operands were equal).JNE label: Jumps if the Zero Flag (ZF) is clear (meaning operands were not equal).
Let's see an example.
section .data
eq_msg db "Numbers are equal!", 0xA
eq_len equ $ - eq_msg
ne_msg db "Numbers are not equal!", 0xA
ne_len equ $ - ne_msg
section .text
global _start
_start:
mov rax, 10
mov rbx, 10 ; Try changing this to 5
cmp rax, rbx ; Compare RAX and RBX
je are_equal ; If equal, jump to are_equal
; Else (not equal)
mov rax, 1
mov rdi, 1
mov rsi, ne_msg
mov rdx, ne_len
syscall
jmp end_program
are_equal:
mov rax, 1
mov rdi, 1
mov rsi, eq_msg
mov rdx, eq_len
syscall
end_program:
mov rax, 60
mov rdi, 0
syscallGreater or Lesser (Signed)
For signed numbers, we use different conditional jumps to check for greater than or less than relationships.
JG label: Jump if Greater (ZF=0 and SF=OF)JGE label: Jump if Greater or Equal (SF=OF)JL label: Jump if Less (SF!=OF)JLE label: Jump if Less or Equal (ZF=1 or SF!=OF)
These rely on combinations of the Sign Flag (SF), Overflow Flag (OF), and Zero Flag (ZF).
section .data
gt_msg db "RAX is greater!", 0xA
gt_len equ $ - gt_msg
lt_msg db "RAX is less!", 0xA
lt_len equ $ - lt_msg
eq_msg db "RAX is equal!", 0xA
eq_len equ $ - eq_msg
section .text
global _start
_start:
mov rax, 5
mov rbx, 10 ; Compare 5 with 10
cmp rax, rbx
jg is_greater ; If RAX > RBX
jl is_less ; If RAX < RBX
; Else, they must be equal
mov rsi, eq_msg
mov rdx, eq_len
jmp print_msg
is_greater:
mov rsi, gt_msg
mov rdx, gt_len
jmp print_msg
is_less:
mov rsi, lt_msg
mov rdx, lt_len
jmp print_msg
print_msg:
mov rax, 1
mov rdi, 1
syscall
mov rax, 60
mov rdi, 0
syscallUnsigned Comparisons (JA, JB)
When dealing with unsigned numbers, the flags are interpreted differently. The Carry Flag (CF) is key here.
JA label: Jump if Above (unsigned greater than) (CF=0 and ZF=0)JAE label: Jump if Above or Equal (unsigned greater than or equal) (CF=0)JB label: Jump if Below (unsigned less than) (CF=1)JBE label: Jump if Below or Equal (unsigned less than or equal) (CF=1 or ZF=1)
Always be mindful if you're comparing signed or unsigned values!
Building an IF-ELSE Block
We can combine CMP and conditional jumps to create if-else logic, just like in high-level languages.
The general pattern is: compare, jump if condition is FALSE to the "else" block, execute "if" block, then jump past "else" block.
section .data
if_msg db "Condition is TRUE!", 0xA
if_len equ $ - if_msg
else_msg db "Condition is FALSE!", 0xA
else_len equ $ - else_msg
section .text
global _start
_start:
mov rax, 20
mov rbx, 10
cmp rax, rbx ; Is RAX > RBX?
jle else_block ; If not (less or equal), jump to else
; IF block (RAX > RBX)
mov rsi, if_msg
mov rdx, if_len
jmp print_and_exit
else_block:
; ELSE block (RAX <= RBX)
mov rsi, else_msg
mov rdx, else_len
print_and_exit:
mov rax, 1
mov rdi, 1
syscall
mov rax, 60
mov rdi, 0
syscallCreating Loops with Jumps
Loops are fundamental for repeating code. In assembly, we combine a label, a comparison, and a conditional jump to create them.
A common pattern involves: initializing a counter, defining a loop label, performing operations, decrementing/incrementing the counter, comparing, and jumping back to the label if the condition is met.
section .data
msg db "Looping... ", 0xA
len equ $ - msg
section .text
global _start
_start:
mov rcx, 3 ; Initialize loop counter
loop_start:
cmp rcx, 0 ; Check if counter is 0
je loop_end ; If it is, exit loop
; Print message
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, len
syscall
dec rcx ; Decrement counter
jmp loop_start ; Jump back to start of loop
loop_end:
mov rax, 60
mov rdi, 0
syscallJump Condition Check
Consider the following assembly snippet. What will be printed if RAX holds the value 5 and RBX holds 10?
section .data
msg_a db "Result A", 0xA
len_a equ $ - msg_a
msg_b db "Result B", 0xA
len_b equ $ - msg_b
section .text
global _start
_start:
; Assume RAX = 5, RBX = 10
cmp rax, rbx
jg print_a
jmp print_b
print_a:
mov rax, 1
mov rdi, 1
mov rsi, msg_a
mov rdx, len_a
syscall
jmp end_program
print_b:
mov rax, 1
mov rdi, 1
mov rsi, msg_b
mov rdx, len_b
syscall
end_program:
mov rax, 60
mov rdi, 0
syscallRecap: Jumps and Loops
Great job! You've learned how to control your program's flow in assembly!
JMPis for unconditional jumps.CMPcompares values and updates the CPU's flags register.- Conditional jumps (like
JE,JNE,JG,JL,JA,JB) check these flags to decide whether to jump. - By combining these, you can create powerful if-else statements and loops.
Next, we'll dive into procedures and stack management to organize your code even further!
常见问题解答
「条件跳转与循环」课时是免费的吗?
是的 — 「条件跳转与循环」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Assembly Language & x86 Low-Level Systems Programming 课程的其余内容,请升级到 CoddyKit PRO。 Assembly Language & x86 Low-Level Systems Programming 课程共包含 4 节课。
「条件跳转与循环」这节课中我会学到什么?
使用比较指令(CMP、TEST)和条件跳转指令(JMP、JE、JNE、JL、JG 等)实现决策和重复任务。 你通过在浏览器中直接运行的动手代码来练习 Assembly Language & x86 Low-Level Systems Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Assembly Language & x86 Low-Level Systems Programming 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Assembly Language & x86 Low-Level Systems Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「条件跳转与循环」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Assembly Language & x86 Low-Level Systems Programming 课中编写并运行代码吗?
能。每节 Assembly Language & x86 Low-Level Systems Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。