Intel 标识寄存器中的常见标志 && 影响
0x0 简述
标识寄存器,8086 下存储于 FLAGS 寄存器,32 位下扩展为 EFLAGS。听起名知其义,即存储相关的标志。这些标识主要由是相关运算指令产生的结果,例如运算结果是否为零,运算是否溢出(进位、借位)等等。常见的基础标识位有 ZF、PF、SF、CF、OF、DF。
0x1 ZF
主要用于标识运算结果是否为零:
mov ax, 2
sub ax, ax
当运算结果为零时,ZF = 1
,否则 ZF = 0
。标识寄存器通常由 add、sub、inc、or、and 等运算符直接影响,对于 mov、push、pop 等传送指令,不会影响到 ZF 标识。
0x2 PF
奇偶数标识位,当运算结果中 1 的位数为偶数时,PF = 1
,反之 PF = 0
。
例如运算结果为 0010B:
mov ax, 1
add ax, 1 ; PF = 0
当运算结果为 0011B 时,1 的总数为偶数:
mov ax, 1
add ax, 2 ; PF = 1
0x3 SF
在 8086 中,使用补码的方式来存储有符号数。对于负数,其最高位使用 1 来标识:
mov al, 10001000b
add al, 1 ; al = 10001001b
当执行运算操作后,al 的最高符号为 1。10001001b 可以当做 137,也作为有符号数 -119。
对于 CPU 而言,当最高符号为 1 时,会将其记录到 SF 标识中,即 SF = 1
。而对于运算结果是看做 137 还是 -119,则是我们的程序实现问题,取决于将数据作为有符号或者无符号数。
0x4 CF
当运算产生进位、借位时,会对 CF 标识位产生影响。
mov al, 0FFh
add al, 1
由于 al 只能存放最大 0xFF 的数值,当继续增加时,产生进位。此时产生的进位并不会存储到 ah 中,也不会将其丢弃,而是更新 CF 标志位: CF = 1
,表示进位产生。
同样的道理,当进行减法运算时,可能会产生借位:
mov al, 97h
mov bl, 98h
sub al, bl
此时 97h < 98h
,产生借位,即实际上是进行 197h - 98h
运算,此时 CF 标识位也会置位。
0x5 OF
OF 标识位主要用于记录有符号数的溢出。
例如,对于一个 8 位的 al 寄存器来讲,能容纳的无符号数范围为 0 - 255
,即 00h - 0FFh
。
对于有符号数,则范围为 -128 - 127
,最高位为符号为,则范围为 10000000b - 01111111b
。
当进行运算时,对于有符号数来讲,可能会超出数值范围:
mov al, 7Fh
add al, 1 ; al = 8Fh
对于无符号来讲,0x8F(128)在数值范围之内;但是对于一个无符号数来讲,已经超出了 -128 - 127
的范围,所以此时 OF = 1
。
0x6 DF
DF 是方向标识位,主要用于标识递增或递减 SI / DI 寄存器:
; 初始化段寄存器
mov ax, 0
mov ds, ax
mov bx, 20h
mov es, bx
xor si, si
xor di, di
; 清除 DF 位
cld
; 拷贝数据,将 ds:si 复制到 es:di
mov cx, 10
rep movsb
当 DF = 0
时,每次复制完成后,SI 和 DI 依次递增;反之,当 DF = 1
时,SI 和 DI 反方向递减。
置位 DF 标识位,递减偏移寄存器:
std
mov cx, 10
rep movsb