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. 边界值溢出(案例1和3):

    • 对8位-128(80h)和32位-2147483648(80000000h)取反时,由于无法表示对应的正数,会产生溢出(OF=1)
  2. 正常取反(案例2):

    • 对1取反得到-1(FFFFh),标志位正常变化
  3. 内存操作(案例4):

    • 演示直接对内存操作数使用NEG指令
  4. 零值测试(案例5):

    • 验证当操作数为0时,CF=0且ZF=1
  5. 标志位存储

    • 使用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(辅助进位标志):根据结果设置

技术说明:

  1. 该操作等效于计算0 - operand
  2. 对内存操作数使用时需要显式指定操作数大小(byte/word/dword)
  3. 对-128(8位)、-32768(16位)或-2147483648(32位)取反时会产生溢出(OF=1)

示例:

assembly 复制代码
NEG AL      ; 8位寄存器取反
NEG [BX]    ; 16位内存操作数取反(需类型声明)
NEG EAX     ; 32位寄存器取反
相关推荐
旧梦吟4 小时前
脚本语言 汇编
汇编
iCxhust5 小时前
8088单板机C语言汇编混合编程实验方法与步骤
c语言·汇编·单片机·嵌入式硬件·微机原理
元亓亓亓10 小时前
考研408--组成原理--day8--汇编指令&不同语句的机器级表示
开发语言·汇编·c#
介一安全1 天前
【Frida Android】实战篇15:Frida检测与绕过——基于/proc/self/maps的攻防实战
android·网络安全·逆向·安全性测试·frida
缘友一世1 天前
计算系统安全速成之机器级编程(数组和指针)【3】
汇编·计算机组成原理·数组和指针
切糕师学AI1 天前
ARM 汇编指令:LDR
汇编·arm开发
网安Ruler2 天前
AC15启动项分析,漏洞分析
逆向
嫂子的姐夫2 天前
005-AES:采招网
爬虫·逆向·aes加密
询问QQ688238862 天前
探索多虚拟电厂联合调度优化模型:集中式算法的实践
汇编
草莓熊Lotso2 天前
C++11 核心特性实战:列表初始化 + 右值引用与移动语义(附完整代码)
java·服务器·开发语言·汇编·c++·人工智能·经验分享