文章目录
-
-
- 关键演示点说明:
- [NEG指令 - 二进制补码取反](#NEG指令 - 二进制补码取反)
-
assembly
; 设置处理器模式和内存模型
.586 ; 使用 586 指令集
.model flat, stdcall ; 平坦内存模型,stdcall 调用约定
option casemap:none ; 区分大小写
; 引入库文件
includelib kernel32.lib ; Windows API 库
includelib msvcrt.lib ; C 运行时库
.data ; 数据段定义
; 测试数据
byteVal db 80h ; -128(有符号最小值)
wordVal dw 0001h ; 1
dwordVal dd 80000000h ; -2147483648(有符号最小值)
zeroVal db 00h ; 0(测试CF标志)
; 结果存储
byteResult db ?
wordResult dw ?
dwordResult dd ?
; 标志位检测
CF_flag db ? ; 进位/借位标志
OF_flag db ? ; 溢出标志
SF_flag db ? ; 符号标志
ZF_flag db ? ; 零标志
.code ; 代码段
main proc
; ---------------------------
; 1. 8位NEG指令演示(有符号溢出)
; ---------------------------
mov al, byteVal ; AL = 80h (-128)
neg al ; AL = -(-128) = -128(溢出)
mov byteResult, al ; 存储结果(仍为80h)
; 标志位变化:
; CF=1(因为源操作数非零)
; OF=1(有符号溢出:-128无法用+128表示)
; SF=1(结果为负)
; ZF=0(结果非零)
; ---------------------------
; 2. 16位NEG指令演示(正常取反)
; ---------------------------
mov ax, wordVal ; AX = 0001h (1)
neg ax ; AX = -1 (FFFFh)
mov wordResult, ax ; 存储结果
; 标志位变化:
; CF=1(因为源操作数非零)
; OF=0(无有符号溢出)
; SF=1(结果为负)
; ZF=0(结果非零)
; ---------------------------
; 3. 32位NEG指令演示(最小值溢出)
; ---------------------------
mov eax, dwordVal ; EAX = 80000000h (-2147483648)
neg eax ; EAX = -(-2147483648) = -2147483648(溢出)
mov dwordResult, eax ; 存储结果(仍为80000000h)
; 标志位变化:
; CF=1(因为源操作数非零)
; OF=1(有符号溢出)
; SF=1(结果为负)
; ZF=0(结果非零)
; ---------------------------
; 4. 内存操作数取反
; ---------------------------
neg byteVal ; byteVal = -(-128) = -128(80h,溢出)
; 标志位与案例1相同
; ---------------------------
; 5. 零值测试(验证CF标志)
; ---------------------------
mov bl, zeroVal ; BL = 0
neg bl ; BL = -0 = 0
; 标志位变化:
; CF=0(因为源操作数为零)
; OF=0(无溢出)
; SF=0(结果非负)
; ZF=1(结果为零)
; ---------------------------
; 标志位存储演示
; ---------------------------
setc CF_flag ; 存储进位标志(最后操作后应为0)
seto OF_flag ; 存储溢出标志(最后操作后应为0)
sets SF_flag ; 存储符号标志(最后操作后应为0)
setz ZF_flag ; 存储零标志(最后操作后应为1)
; ---------------------------
; 程序退出
; ---------------------------
xor eax, eax ; 返回码 0
ret
main endp
end main
关键演示点说明:
-
边界值溢出(案例1和3):
- 对8位-128(80h)和32位-2147483648(80000000h)取反时,由于无法表示对应的正数,会产生溢出(OF=1)
-
正常取反(案例2):
- 对1取反得到-1(FFFFh),标志位正常变化
-
内存操作(案例4):
- 演示直接对内存操作数使用NEG指令
-
零值测试(案例5):
- 验证当操作数为0时,CF=0且ZF=1
-
标志位存储:
- 使用
setc
/seto
等指令将标志位存入变量,便于调试观察
- 使用
所有测试案例均展示了NEG指令的核心特性:对操作数进行二进制补码取反(等价于0-operand),并正确设置处理器标志位。
NEG指令 - 二进制补码取反
操作码 | 指令格式 | 说明 |
---|---|---|
F6 /3 | NEG r/m8 | 对8位寄存器/内存操作数取补码 |
F7 /3 | NEG r/m16 | 对16位寄存器/内存操作数取补码 |
F7 /3 | NEG r/m32 | 对32位寄存器/内存操作数取补码 |
操作语义:
IF DEST == 0
THEN CF ← 0
ELSE CF ← 1;
FI;
DEST ← 0 - (DEST)
标志位影响:
- CF(进位标志):源操作数为0时清零,否则置1
- OF(溢出标志):根据结果设置
- SF(符号标志):根据结果设置
- ZF(零标志):根据结果设置
- AF(辅助进位标志):根据结果设置
技术说明:
- 该操作等效于计算
0 - operand
- 对内存操作数使用时需要显式指定操作数大小(byte/word/dword)
- 对-128(8位)、-32768(16位)或-2147483648(32位)取反时会产生溢出(OF=1)
示例:
assembly
NEG AL ; 8位寄存器取反
NEG [BX] ; 16位内存操作数取反(需类型声明)
NEG EAX ; 32位寄存器取反