news 2026/4/18 0:22:31

MASM 中的 ADD 指令详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MASM 中的 ADD 指令详解

文章目录

    • MASM 中的 ADD 指令详解
      • 一、基本格式
      • 二、操作数组合规则
      • 三、操作数尺寸支持
      • 四、对标志位的影响
      • 五、具体示例
        • 示例1:寄存器与立即数
        • 示例2:寄存器与寄存器
        • 示例3:内存操作
        • 示例4:带进位的连续加法
      • 六、特殊用法
        • 1. 地址计算
        • 2. 数组访问
        • 3. 优化技巧
      • 七、注意事项
      • 八、编码示例
      • 九、性能考虑
      • 十、常见错误
    • 1. **有符号数溢出(Overflow)**
      • 例(8位有符号数):
    • 2. **无符号数进位(Carry)**
      • 例(8位无符号数):
    • 3. 对比示例
    • 4. x86 指令对标志位的影响
    • 5. 检测方式
    • 6. 总结
  • 代码示例一
  • 简单的ADD指令演示程序
    • 关键演示点
      • 1. **标志位同时设置**
      • 2. **不同类型数据的相同操作**
      • 3. **标志位的双重含义**
    • 运行观察建议
    • 核心理解
  • 代码示例二

MASM 中的 ADD 指令详解

一、基本格式

ADD 目标操作数, 源操作数

功能:将源操作数与目标操作数相加,结果存回目标操作数。

二、操作数组合规则

目标操作数源操作数是否合法示例
寄存器立即数ADD AX, 5
寄存器寄存器ADD EAX, EBX
寄存器内存ADD ECX, [mem]
内存立即数ADD [mem], 10
内存寄存器ADD [mem], EDX
内存内存非法操作

三、操作数尺寸支持

  1. 8位运算ADD AL, BL

  2. 16位运算ADD AX, BX

  3. 32位运算ADD EAX, EBX

  4. 64位运算(x64):ADD RAX, RBX

四、对标志位的影响

ADD AL, CL ; 影响所有状态标志: ; CF(进位标志):无符号溢出时置1 ; PF(奇偶标志):结果低8位中1的个数为偶数时置1 ; AF(辅助进位):低4位向高4位进位时置1 ; ZF(零标志):结果为0时置1 ; SF(符号标志):结果为负时置1 ; OF(溢出标志):有符号溢出时置1

五、具体示例

示例1:寄存器与立即数
MOV AX, 1000h ADD AX, 2000h ; AX = 3000h, CF=0, ZF=0, SF=0
示例2:寄存器与寄存器
MOV EAX, 0FFFFFFFFh MOV EBX, 1 ADD EAX, EBX ; EAX = 0, CF=1, ZF=1, OF=0
示例3:内存操作
.data value DWORD 12345678h result DWORD ? .code MOV EAX, 87654321h ADD value, EAX ; value = 99999999h ADD EAX, value ; EAX = 0FFFFFFFFh
示例4:带进位的连续加法
; 64位加法(使用32位寄存器) MOV EAX, dword ptr [num1_low] MOV EDX, dword ptr [num1_high] ADD EAX, dword ptr [num2_low] ; 低32位相加 ADC EDX, dword ptr [num2_high] ; 高32位带进位相加

六、特殊用法

1. 地址计算
ADD ESI, TYPE DWORD ; ESI增加4(DWORD大小)
2. 数组访问
MOV EBX, 2 ; 索引 MOV EAX, [array + EBX*4] ; 等价于ADD计算偏移
3. 优化技巧
; 使用LEA进行加法(不改变标志位) LEA EAX, [EAX + EBX*2 + 10] ; EAX = EAX + EBX*2 + 10

七、注意事项

  1. 操作数尺寸必须匹配

    ADD AX, BL ; 错误:尺寸不匹配 ADD AL, BL ; 正确:都是8位
  2. 内存操作数需要类型说明

    ADD [mem], 5 ; 错误:未指定尺寸 ADD BYTE PTR [mem], 5 ; 正确 ADD DWORD PTR [mem], 5 ; 正确
  3. 立即数符号扩展

    ADD EAX, -1 ; 实际编码为FFFFFFFFh
  4. 有符号与无符号的差异

    • 无符号数:看CF(进位标志)

    • 有符号数:看OF(溢出标志)

八、编码示例

.386 .model flat, stdcall .stack 4096 .data num1 DWORD 1000 num2 DWORD 2000 sum DWORD 0 .code main PROC ; 示例1:寄存器加法 MOV EAX, num1 ADD EAX, num2 ; EAX = 3000 MOV sum, EAX ; 示例2:内存直接加法 ADD num1, 500 ; num1 = 1500 ; 示例3:多精度加法 MOV AX, 0FFFFh MOV BX, 1 ADD AX, BX ; AX=0, CF=1, ZF=1 ; 示例4:循环累加 MOV ECX, 10 MOV EAX, 0 L1: ADD EAX, ECX LOOP L1 ; EAX = 10+9+...+1 = 55 RET main ENDP END main

九、性能考虑

  1. 现代CPU中:ADD指令通常只需要1个时钟周期

  2. 依赖链:连续的ADD指令可能形成依赖链

  3. 宏融合:某些情况下ADD可与CMP/JCC指令融合

十、常见错误

; 错误示例 ADD 5, AX ; 立即数不能作为目标 ADD [EAX], [EBX] ; 内存到内存不支持 ADD AX, EAX ; 尺寸不匹配 ; 正确写法 ADD AX, 5 ADD AX, BX MOV ECX, [EBX] ADD [EAX], ECX

ADD指令是x86汇编中最基础、最常用的算术指令,理解其工作原理和标志位影响对于编写正确的汇编程序至关重要。

在 x86 汇编中,有符号数溢出无符号数进位是两个不同的概念,它们对应不同的标志位:


1.有符号数溢出(Overflow)

  • 检测标志OF(Overflow Flag)
  • 溢出条件:两个有符号数相加,结果超出了有符号数能表示的范围(对 8 位是 -128~127,16 位是 -32768~32767,32 位是 -2³¹~2³¹-1,64 位是 -2⁶³~2⁶³-1)。

例(8位有符号数):

mov al, 100 ; 十进制 100(有符号为正) add al, 50 ; 结果 150,但 8 位有符号范围是 -128~127,150 > 127 ; 此时 OF = 1(溢出)
mov al, -100 ; 有符号 -100 add al, -50 ; 结果 -150,小于 -128,同样 OF = 1

常见溢出情况
正数 + 正数 → 结果为负(符号位错误)
负数 + 负数 → 结果为正(符号位错误)


2.无符号数进位(Carry)

  • 检测标志CF(Carry Flag)
  • 进位条件:两个无符号数相加,结果超出了无符号数能表示的范围(对 8 位是 0~255,16 位是 0~65535,等等)。

例(8位无符号数):

mov al, 200 ; 无符号 200 add al, 100 ; 结果 300,但 8 位无符号最大 255,300 > 255 ; 此时 CF = 1(进位)
mov al, 255 ; 无符号 255 add al, 1 ; 结果 256(实际 AL=0),CF = 1

3. 对比示例

假设 8 位运算:

mov al, 0x80 ; 二进制 10000000 mov bl, 0x80 add al, bl
  • 有符号视角
    al = -128bl = -128,和 = -256(超出 8 位有符号范围) →OF = 1
  • 无符号视角
    al = 128bl = 128,和 = 256(超出 8 位无符号范围) →CF = 1

在这个例子中,OF 和 CF 同时为 1


4. x86 指令对标志位的影响

  • ADD指令同时影响OFCF(分别用于有符号溢出和无符号进位判断)。
  • ADC带进位加同样影响两者。
  • INC指令不影响CF,只影响OF(常用于有符号数循环计数)。

5. 检测方式

  • 有符号溢出检查:JO(溢出跳转)或JNO
  • 无符号进位检查:JC(进位跳转)或JNC

6. 总结

数类型超出范围判断标志示例(8位)导致标志置 1 的情况
有符号数OF(溢出标志)100 + 50 = 150(>127)
无符号数CF(进位标志)200 + 100 = 300(>255)

关键点
同一个二进制加法,从有符号角度看可能溢出,从无符号角度看可能进位,或者两者同时发生,或者都不发生。CPU 会同时设置 OF 和 CF,程序根据数的解释方式选择检查哪个标志。

代码示例一

简单的ADD指令演示程序

以下是一个精简的ADD指令演示程序,重点展示ADD如何影响标志寄存器的不同情况:

.386 .model flat, stdcall option casemap:none ExitProcess PROTO, dwExitCode:DWORD .data ; 测试数据 byte1 db 127 ; 01111111b byte2 db 128 ; 10000000b byte3 db 255 ; 11111111b ; 标志存储 cf_flag db 0 ; 进位标志 of_flag db 0 ; 溢出标志 zf_flag db 0 ; 零标志 sf_flag db 0 ; 符号标志 ; 结果存储 result db 0 .code main proc ; 演示1: 正数加法 - 无进位,无溢出 ; AL = 50 + 30 = 80 MOV AL, 50 ADD AL, 30 ; 二进制: 00110010 + 00011110 = 01010000 CALL save_flags ; 保存标志状态 ; 演示2: 有符号正溢出 ; AL = 127 + 1 = -128 (有符号溢出) MOV AL, 127 ; 01111111b = +127 ADD AL, 1 ; 10000000b = -128 CALL save_flags ; OF=1, SF=1, ZF=0, CF=0 ; 演示3: 无符号进位 ; AL = 255 + 1 = 0 (无符号进位) MOV AL, 255 ; 11111111b = 255 ADD AL, 1 ; 00000000b = 0 CALL save_flags ; CF=1, ZF=1, OF=0, SF=0 ; 演示4: 负溢出 ; AL = -128 + -1 = 127 (有符号负溢出) MOV AL, -128 ; 10000000b = -128 ADD AL, -1 ; 01111111b = +127 CALL save_flags ; OF=1, SF=0, CF=1 ; 演示5: 符号标志 ; AL = 64 + -100 = -36 MOV AL, 64 ADD AL, -100 ; 结果应为负数 CALL save_flags ; SF=1, OF=0, CF=1 ; 演示6: 零结果 ; AL = -100 + 100 = 0 MOV AL, -100 ADD AL, 100 CALL save_flags ; ZF=1, SF=0, OF=0, CF=1 ; 演示7: 同时有符号溢出和无符号进位 ; AL = -1 + -1 = -2 (无符号: 255 + 255 = 254 带进位) MOV AL, -1 ; 11111111b ADD AL, -1 ; 11111110b CALL save_flags ; SF=1, OF=0, CF=1 ; 演示8: 16位寄存器示例 MOV AX, 32767 ; 0111111111111111b ADD AX, 1 ; 1000000000000000b ; 注意: 16位操作同样影响标志 ; 程序结束 push 0 call ExitProcess main endp ; ============================================ ; 保存标志状态的子程序 ; ============================================ save_flags proc MOV result, AL ; 保存结果 ; 保存进位标志 JC cf_set MOV cf_flag, 0 JMP check_of cf_set: MOV cf_flag, 1 check_of: ; 保存溢出标志 JO of_set MOV of_flag, 0 JMP check_zf of_set: MOV of_flag, 1 check_zf: ; 保存零标志 JZ zf_set MOV zf_flag, 0 JMP check_sf zf_set: MOV zf_flag, 1 check_sf: ; 保存符号标志 JS sf_set MOV sf_flag, 0 JMP done sf_set: MOV sf_flag, 1 done: ; 在这里可以设置断点查看标志状态 RET save_flags endp ; ============================================ ; 演示标志位如何定义数据类型 ; ============================================ type_demo proc ; 同一数据,不同解释 MOV AL, 200 ; 二进制: 11001000b ; 作为无符号数: 200 ADD AL, 100 ; 200 + 100 = 44 (CF=1) JC unsigned_overflow ; 无符号数溢出处理 ; 作为有符号数: -56 ADD AL, -100 ; -56 + -100 = 44 (OF=0, 正确) JO signed_overflow ; 有符号数溢出处理 RET unsigned_overflow: ; 处理无符号溢出 RET signed_overflow: ; 处理有符号溢出 RET type_demo endp end main

关键演示点

1.标志位同时设置

每个ADD指令后,所有相关标志位同时被设置:

  • CF(进位标志):无符号运算的溢出
  • OF(溢出标志):有符号运算的溢出
  • ZF(零标志):结果是否为0
  • SF(符号标志):结果是否为负

2.不同类型数据的相同操作

; 同样的二进制操作,不同解释 MOV AL, 10000000b ; 二进制: 10000000 ; 解释1: 无符号数128 ADD AL, 1 ; 129, CF=0 ; 解释2: 有符号数-128 ADD AL, 1 ; -127, OF=0 (没有溢出范围)

3.标志位的双重含义

; 示例: AL = 11111111b (255或-1) ADD AL, 11111111b ; 加同样的值 ; 无符号视角: 255 + 255 = 254 (CF=1) ; 有符号视角: -1 + -1 = -2 (OF=0)

运行观察建议

  1. 使用调试器(如OllyDbg或x64dbg)单步执行
  2. save_flags子程序返回后观察:
    • result:存储计算结果
    • cf_flag,of_flag,zf_flag,sf_flag:标志状态
  3. 注意观察相同的ADD操作如何同时设置多个标志

核心理解

ADD指令本身无类型

  • 它只是执行二进制加法
  • 同时设置所有可能的标志位
  • 程序员的后续选择定义了数据类型:
    • 检查CF→ 视为无符号数
    • 检查OF→ 视为有符号数
    • 检查ZF→ 比较操作
    • 检查SF→ 符号判断

这个精简程序清晰地展示了汇编层面"数据无类型"的本质,以及如何通过标志位检查来赋予数据具体的类型含义。

代码示例二

.386 .model flat, stdcall option casemap:none ExitProcess PROTO, dwExitCode:DWORD .data ; 通用数据定义 data8_1 db 127 ; 01111111b data8_2 db 128 ; 10000000b data8_3 db 255 ; 11111111b data16_1 dw 32767 ; 0111111111111111b data16_2 dw 32768 ; 1000000000000000b data32_1 dd 2147483647 ; 01111111111111111111111111111111b data32_2 dd 2147483648 ; 10000000000000000000000000000000b ; 结果存储 result8 db 0 result16 dw 0 result32 dd 0 ; 标志存储 flags_cf db 0 flags_of db 0 flags_zf db 0 flags_sf db 0 .code ; ============================================ ; 演示1:基本ADD指令 - 8位运算 ; ============================================ demo1_add_basic proc ; 清空结果 MOV result8, 0 ; 示例1: 简单加法 MOV AL, 50 ADD AL, 30 ; AL = 80 MOV result8, AL ; 示例2: 带进位的加法 MOV BL, 200 ADD BL, 100 ; BL = 44 (300 mod 256), CF=1 JC demo1_carry_set JMP demo1_no_carry demo1_carry_set: MOV flags_cf, 1 JMP demo1_next demo1_no_carry: MOV flags_cf, 0 demo1_next: ; 示例3: 零结果 MOV CL, 255 ADD CL, 1 ; CL = 0, ZF=1 JZ demo1_zero_set JMP demo1_not_zero demo1_zero_set: MOV flags_zf, 1 JMP demo1_end demo1_not_zero: MOV flags_zf, 0 demo1_end: RET demo1_add_basic endp ; ============================================ ; 演示2:有符号溢出检测 ; ============================================ demo2_signed_overflow proc ; 清空标志 MOV flags_of, 0 ; 情况1: 正溢出 (127 + 1) MOV AL, 127 ; 最大值 ADD AL, 1 ; 127 + 1 = -128 (溢出) JO demo2_overflow_case1 ; 没有溢出,继续 JMP demo2_case2 demo2_overflow_case1: MOV flags_of, 1 MOV result8, AL ; 保存结果: -128 demo2_case2: ; 情况2: 负溢出 (-128 + -1) MOV BL, -128 ; 最小值 ADD BL, -1 ; -128 + -1 = 127 (溢出) JO demo2_overflow_case2 ; 没有溢出 JMP demo2_case3 demo2_overflow_case2: MOV flags_of, 1 MOV result8, BL ; 保存结果: 127 demo2_case3: ; 情况3: 没有溢出 (100 + 20) MOV CL, 100 ADD CL, 20 ; 120, 没有溢出 JO demo2_overflow_case3 JMP demo2_no_overflow_case3 demo2_overflow_case3: MOV flags_of, 1 JMP demo2_end demo2_no_overflow_case3: MOV flags_of, 0 MOV result8, CL ; 保存结果: 120 demo2_end: RET demo2_signed_overflow endp ; ============================================ ; 演示3:无符号进位检测 ; ============================================ demo3_unsigned_carry proc ; 清空标志 MOV flags_cf, 0 ; 情况1: 产生进位 (255 + 1) MOV AL, 255 ; 无符号最大值 ADD AL, 1 ; 256, 进位 JC demo3_carry_case1 ; 没有进位 JMP demo3_case2 demo3_carry_case1: MOV flags_cf, 1 MOV result8, AL ; 保存结果: 0 demo3_case2: ; 情况2: 没有进位 (200 + 50) MOV BL, 200 ADD BL, 50 ; 250, 没有进位 JC demo3_carry_case2 JMP demo3_no_carry_case2 demo3_carry_case2: MOV flags_cf, 1 JMP demo3_case3 demo3_no_carry_case2: MOV flags_cf, 0 MOV result8, BL ; 保存结果: 250 demo3_case3: ; 情况3: 边界情况 (254 + 1) MOV CL, 254 ADD CL, 1 ; 255, 没有进位 JC demo3_carry_case3 JMP demo3_no_carry_case3 demo3_carry_case3: MOV flags_cf, 1 JMP demo3_end demo3_no_carry_case3: MOV flags_cf, 0 MOV result8, CL ; 保存结果: 255 demo3_end: RET demo3_unsigned_carry endp ; ============================================ ; 演示4:符号标志(SF)检测 ; ============================================ demo4_sign_flag proc ; 清空标志 MOV flags_sf, 0 ; 情况1: 正数加正数得到正数 MOV AL, 50 ADD AL, 30 ; AL = 80, SF=0 JS demo4_negative_case1 JMP demo4_positive_case1 demo4_negative_case1: MOV flags_sf, 1 JMP demo4_case2 demo4_positive_case1: MOV flags_sf, 0 MOV result8, AL ; 保存结果: 80 demo4_case2: ; 情况2: 正数加负数得到负数 MOV BL, 50 ADD BL, -100 ; BL = -50, SF=1 JS demo4_negative_case2 JMP demo4_positive_case2 demo4_negative_case2: MOV flags_sf, 1 MOV result8, BL ; 保存结果: -50 demo4_positive_case2: MOV flags_sf, 0 JMP demo4_case3 demo4_case3: ; 情况3: 负数加负数得到负数 MOV CL, -50 ADD CL, -30 ; CL = -80, SF=1 JS demo4_negative_case3 JMP demo4_positive_case3 demo4_negative_case3: MOV flags_sf, 1 MOV result8, CL ; 保存结果: -80 demo4_positive_case3: MOV flags_sf, 0 demo4_end: RET demo4_sign_flag endp ; ============================================ ; 演示5:零标志(ZF)检测 ; ============================================ demo5_zero_flag proc ; 清空标志 MOV flags_zf, 0 ; 情况1: 非零结果 MOV AL, 50 ADD AL, 30 ; AL = 80, ZF=0 JZ demo5_zero_case1 JMP demo5_nonzero_case1 demo5_zero_case1: MOV flags_zf, 1 JMP demo5_case2 demo5_nonzero_case1: MOV flags_zf, 0 MOV result8, AL ; 保存结果: 80 demo5_case2: ; 情况2: 零结果 (255 + 1) MOV BL, 255 ADD BL, 1 ; BL = 0, ZF=1 JZ demo5_zero_case2 JMP demo5_nonzero_case2 demo5_zero_case2: MOV flags_zf, 1 MOV result8, BL ; 保存结果: 0 demo5_nonzero_case2: MOV flags_zf, 0 demo5_end: RET demo5_zero_flag endp ; ============================================ ; 演示6:溢出与进位的对比 ; ============================================ demo6_overflow_vs_carry proc ; 同时检测OF和CF ; 示例1: 有符号溢出,无符号无进位 (127 + 1) MOV AL, 127 ADD AL, 1 ; AL = -128 ; 检查OF JO demo6_of_set_1 JMP demo6_of_clear_1 demo6_of_set_1: MOV flags_of, 1 demo6_of_clear_1: MOV flags_of, 0 ; 检查CF JC demo6_cf_set_1 JMP demo6_cf_clear_1 demo6_cf_set_1: MOV flags_cf, 1 demo6_cf_clear_1: MOV flags_cf, 0 ; 保存结果 MOV result8, AL ; 示例2: 无符号进位,有符号无溢出 (255 + 1) MOV BL, 255 ADD BL, 1 ; BL = 0 ; 检查OF JO demo6_of_set_2 JMP demo6_of_clear_2 demo6_of_set_2: MOV flags_of, 1 demo6_of_clear_2: MOV flags_of, 0 ; 检查CF JC demo6_cf_set_2 JMP demo6_cf_clear_2 demo6_cf_set_2: MOV flags_cf, 1 demo6_cf_clear_2: MOV flags_cf, 0 ; 保存结果 MOV result8, BL demo6_end: RET demo6_overflow_vs_carry endp ; ============================================ ; 演示7:16位ADD指令 ; ============================================ demo7_add_16bit proc ; 清空结果 MOV result16, 0 ; 示例1: 简单16位加法 MOV AX, 10000 ADD AX, 20000 ; AX = 30000 MOV result16, AX ; 示例2: 16位有符号溢出 MOV BX, 32767 ; 最大值 ADD BX, 1 ; 溢出 JO demo7_overflow_16 JMP demo7_no_overflow_16 demo7_overflow_16: MOV flags_of, 1 MOV result16, BX ; 保存溢出结果 JMP demo7_case3 demo7_no_overflow_16: MOV flags_of, 0 MOV result16, BX demo7_case3: ; 示例3: 16位无符号进位 MOV CX, 65535 ; 无符号最大值 ADD CX, 1 ; 进位 JC demo7_carry_16 JMP demo7_no_carry_16 demo7_carry_16: MOV flags_cf, 1 MOV result16, CX ; 保存结果: 0 JMP demo7_end demo7_no_carry_16: MOV flags_cf, 0 MOV result16, CX demo7_end: RET demo7_add_16bit endp ; ============================================ ; 演示8:32位ADD指令 ; ============================================ demo8_add_32bit proc ; 清空结果 MOV result32, 0 ; 示例1: 简单32位加法 MOV EAX, 1000000000 MOV EBX, 1500000000 ADD EAX, EBX ; EAX = 2500000000 MOV result32, EAX ; 示例2: 32位有符号溢出 MOV ECX, 2147483647 ; 最大值 ADD ECX, 1 ; 溢出 JO demo8_overflow_32 JMP demo8_no_overflow_32 demo8_overflow_32: MOV flags_of, 1 MOV result32, ECX ; 保存溢出结果 JMP demo8_case3 demo8_no_overflow_32: MOV flags_of, 0 MOV result32, ECX demo8_case3: ; 示例3: 32位无符号进位 MOV EDX, 0FFFFFFFFh ; 无符号最大值 ADD EDX, 1 ; 进位 JC demo8_carry_32 JMP demo8_no_carry_32 demo8_carry_32: MOV flags_cf, 1 MOV result32, EDX ; 保存结果: 0 JMP demo8_end demo8_no_carry_32: MOV flags_cf, 0 MOV result32, EDX demo8_end: RET demo8_add_32bit endp ; ============================================ ; 演示9:ADD指令与内存操作数 ; ============================================ demo9_add_memory proc ; 示例1: 寄存器加内存 MOV AL, 100 ADD AL, data8_1 ; AL = 100 + 127 = 227 (溢出) JO demo9_overflow_mem1 JMP demo9_no_overflow_mem1 demo9_overflow_mem1: MOV flags_of, 1 MOV result8, AL JMP demo9_case2 demo9_no_overflow_mem1: MOV flags_of, 0 MOV result8, AL demo9_case2: ; 示例2: 内存加立即数 MOV data8_2, 200 ADD data8_2, 100 ; 内存 = 44 (300 mod 256), CF=1 JC demo9_carry_mem2 JMP demo9_no_carry_mem2 demo9_carry_mem2: MOV flags_cf, 1 MOV AL, data8_2 MOV result8, AL JMP demo9_case3 demo9_no_carry_mem2: MOV flags_cf, 0 MOV AL, data8_2 MOV result8, AL demo9_case3: ; 示例3: 内存加寄存器 MOV data8_3, 50 MOV BL, 30 ADD data8_3, BL ; 内存 = 80 MOV AL, data8_3 MOV result8, AL demo9_end: RET demo9_add_memory endp ; ============================================ ; 演示10:安全加法函数 ; ============================================ demo10_safe_addition proc ; 安全的加法函数,检测溢出 ; 函数签名: safe_add(EAX: 数1, EBX: 数2) ; 返回: EAX = 结果,CF = 是否出错 ; 示例1: 安全的加法 MOV EAX, 1000 MOV EBX, 2000 CALL safe_add_proc ; 保存结果 MOV result32, EAX ; 示例2: 会溢出的加法 MOV EAX, 2147483647 MOV EBX, 1 CALL safe_add_proc ; 保存结果 MOV result32, EAX ; 示例3: 负溢出 MOV EAX, -2147483648 MOV EBX, -1 CALL safe_add_proc ; 保存结果 MOV result32, EAX RET demo10_safe_addition endp ; 安全的加法函数实现 safe_add_proc proc ; 输入: EAX = 数1, EBX = 数2 ; 输出: EAX = 结果,如果溢出则CF=1 ADD EAX, EBX JO safe_add_overflow ; 没有溢出,正常返回 CLC ; 清除进位标志表示成功 RET safe_add_overflow: ; 溢出处理:返回最大值并设置错误标志 MOV EAX, 7FFFFFFFh ; 返回最大值 STC ; 设置进位标志表示错误 RET safe_add_proc endp ; ============================================ ; 主程序:按顺序执行所有演示 ; ============================================ main proc ; 演示1: 基本ADD指令 CALL demo1_add_basic ; 演示2: 有符号溢出检测 CALL demo2_signed_overflow ; 演示3: 无符号进位检测 CALL demo3_unsigned_carry ; 演示4: 符号标志检测 CALL demo4_sign_flag ; 演示5: 零标志检测 CALL demo5_zero_flag ; 演示6: 溢出与进位的对比 CALL demo6_overflow_vs_carry ; 演示7: 16位ADD指令 CALL demo7_add_16bit ; 演示8: 32位ADD指令 CALL demo8_add_32bit ; 演示9: ADD指令与内存操作数 CALL demo9_add_memory ; 演示10: 安全加法函数 CALL demo10_safe_addition ; 程序结束 push 0 call ExitProcess main endp end main
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 8:49:08

揭秘Open-AutoGLM如何实现发票0误差自动归档:AI驱动的财税新革命

第一章:揭秘Open-AutoGLM如何实现发票0误差自动归档:AI驱动的财税新革命在传统财务流程中,发票归档长期依赖人工录入与分类,不仅效率低下,还极易因人为疏忽导致数据错误。Open-AutoGLM 的出现彻底改变了这一局面。该系…

作者头像 李华
网站建设 2026/4/17 22:21:26

10个AI论文工具,助研究生高效完成毕业论文!

10个AI论文工具,助研究生高效完成毕业论文! AI 工具如何改变论文写作的未来 在研究生阶段,撰写毕业论文是一项既复杂又耗时的任务。从选题到开题,再到撰写初稿和反复修改,每一个环节都对学生的学术能力和时间管理提出了…

作者头像 李华
网站建设 2026/4/18 6:31:06

【紧急预警】传统IoT控制架构即将淘汰?Open-AutoGLM已全面接管

第一章:Open-AutoGLM物联网设备联动控制的革命性突破Open-AutoGLM 作为新一代开源自动化语言模型框架,首次将大语言模型的推理能力与物联网(IoT)设备控制深度融合,实现了跨设备、跨协议的智能联动。其核心在于通过自然…

作者头像 李华
网站建设 2026/4/17 14:13:37

基于YOLOv12的密集行人识别检测系统(YOLOv12深度学习+YOLO数据集+UI界面+登录注册界面+Python项目源码+模型)

一、项目介绍 本文设计并实现了一种基于YOLOv12深度学习模型的密集行人识别检测系统,结合YOLO数据集与用户友好的UI界面,构建了一套完整的行人检测解决方案。系统采用Python开发,包含登录注册功能,并基于YOLOv12算法优化了密集场…

作者头像 李华
网站建设 2026/4/18 4:40:34

基于YOLOv12的红外森林火灾火焰烟雾识别检测系统(YOLOv12深度学习+YOLO数据集+UI界面+登录注册界面+Python项目源码+模型)

一、项目介绍 森林火灾是威胁生态环境和人类安全的重要灾害之一,快速准确的火灾检测对灾害防控至关重要。本文基于深度学习目标检测算法YOLOv12,构建了一套红外森林火灾火焰与烟雾检测系统。该系统利用红外图像数据,通过YOLOv12模型实现了对…

作者头像 李华