10.跳转

1. 基本命令

jmp loop #无条件
Instruction  指令 Condition  条件 Description  描述
jz D = 0 目标等于零
jnz D != 0 目的地不等于零
js D < 0 目标为负数
jns D >= 0 目的地不是负数 (即 0 或正数)
jg D > S 目标大于
jge D >= S 目标大于或等于
jl D < S 目标小于
jle D <= S 目标小于或等于

有关条件的完整列表,我们可以参考最新的英特尔 x86_64 手册

2. RFLAGS 寄存器

RFLAGS 寄存器与任何其他寄存器一样由 64 位组成。但是,该寄存器不保存值,而是保存标志位。每个位“或位集”根据最后一条指令的值变为 1 或 0

Bit(s) 0 1 2 3 4 5 6 7 8 9 10 11 12-13 14 15 16 17 18 19 20 21 22-63
Label (1/0) CF (CY/NC) 1 PF (PE/PO) 0 AF (AC/NA) 0 ZF (ZR/NZ) SF (NC/PL) TF IF (EL/DI) DF (DN/UP) OF (OV/NV) IOPL NT 0 RF VM AC VIF VIP ID 0
Description Carry Flag Reserved Parity Flag Reserved Auxiliary Carry Flag Reserved Zero Flag Sign Flag Trap Flag Interrupt Flag Direction Flag Overflow Flag I/O Privilege Level Nested Task Reserved Resume Flag Virtual-x86 Mode Alignment Check / Access Control Virtual Interrupt Flag Virtual Interrupt Pending Identification Flag Reserved

常用标志:

  • 进位标志 CF: 指示我们是否有浮点。
  • 奇偶校验标志 PF: 指示数字是奇数还是偶数。
  • 零标志 ZF:指示数字是否为零。[1]
  • 符号标志 SF: 指示寄存器是否为负数。

3. cmp

cmp rax, rbx -> rax - rbx #(第一个操作数 - 第二个操作数)来设置 RFLAGS

注: 在 cmp 指令中,第一个操作数(即目标)必须是寄存器,而另一个可以是寄存器、变量或立即数。

4. 作业

https://academy.hackthebox.com/storage/modules/85/conditional.zip
附件中的汇编代码一直循环。请尝试修改 (mov rax, 5) 使其不再循环。哪个十六进制值可以避免循环?

 

global _start

section .text
_start:
    mov rax, 2      ; 改为 2(十六进制 0x2)
    imul rax, 5
loop:
    cmp rax, 10
    jnz loop

  1. 检测运算结果最低字节(低8位)中 1 的个数是否为偶数。
    PF = 1:最低字节中 1 的个数为偶数(包括 0 个)
    PF = 0:最低字节中 1 的个数为奇数
    计算示例:
    mov al, 0x07 ; al = 0000 0111(3个1)→ 奇数 → PF=0
    mov al, 0x03 ; al = 0000 0011(2个1)→ 偶数 → PF=1
    mov al, 0xFF ; al = 1111 1111(8个1)→ 偶数 → PF=1
    mov al, 0x00 ; al = 0000 0000(0个1)→ 偶数 → PF=1↩︎