Day 6: 算术运算指令
本章介绍CPU的算术运算指令,包括加法、减法、乘法、除法等基本运算。
1. 加法指令
1.1 ADD
; ADD 目标, 源 ; 目标 = 目标 + 源 add eax, 5 ; EAX = EAX + 5 add eax, ebx ; EAX = EAX + EBX add eax, [var] ; EAX = EAX + [var] add [var], eax ; [var] = [var] + EAX add dword [var], 10 ; [var] = [var] + 10 ; 影响标志位:CF, OF, SF, ZF, AF, PF1.2 ADC(带进位加法)
; ADC - Add with Carry ; 目标 = 目标 + 源 + CF ; 用于多字节加法 ; 例:64位加法(在32位系统上) ; EDX:EAX + ECX:EBX add eax, ebx ; 低32位相加 adc edx, ecx ; 高32位相加(含进位)1.3 INC
; INC - 加1 inc eax ; EAX++ inc byte [var] ; 字节加1 inc dword [var] ; 双字加1 ; 注意:INC不影响CF标志位! ; 这是和 add eax, 1 的区别2. 减法指令
2.1 SUB
; SUB 目标, 源 ; 目标 = 目标 - 源 sub eax, 5 ; EAX = EAX - 5 sub eax, ebx ; EAX = EAX - EBX sub [var], eax ; [var] = [var] - EAX ; 影响标志位:CF, OF, SF, ZF, AF, PF2.2 SBB(带借位减法)
; SBB - Subtract with Borrow ; 目标 = 目标 - 源 - CF ; 用于多字节减法 sub eax, ebx ; 低32位相减 sbb edx, ecx ; 高32位相减(含借位)2.3 DEC
; DEC - 减1 dec eax ; EAX-- dec byte [var] ; 注意:DEC不影响CF标志位!2.4 NEG
; NEG - 取负(求补码) ; 目标 = 0 - 目标 mov eax, 5 neg eax ; EAX = -5 (0xFFFFFFFB) mov eax, -10 neg eax ; EAX = 103. 乘法指令
3.1 MUL(无符号乘法)
; MUL 源 ; 隐式使用AL/AX/EAX作为另一个操作数 ; 8位乘法:AX = AL × 源 mov al, 10 mov bl, 20 mul bl ; AX = 10 × 20 = 200 ; 16位乘法:DX:AX = AX × 源 mov ax, 1000 mov bx, 100 mul bx ; DX:AX = 100000 ; 32位乘法:EDX:EAX = EAX × 源 mov eax, 100000 mov ebx, 100000 mul ebx ; EDX:EAX = 10000000000 ; 结果可能是操作数的两倍大小!3.2 IMUL(有符号乘法)
; 单操作数形式(类似MUL) imul ebx ; EDX:EAX = EAX × EBX(有符号) ; 双操作数形式 imul eax, ebx ; EAX = EAX × EBX ; 三操作数形式 imul eax, ebx, 10 ; EAX = EBX × 10 imul eax, [var], 5 ; EAX = [var] × 5 ; 三操作数形式最灵活!4. 除法指令
4.1 DIV(无符号除法)
; DIV 源 ; 被除数隐式在AX/DX:AX/EDX:EAX中 ; 8位除法:AL = AX ÷ 源, AH = 余数 mov ax, 100 mov bl, 7 div bl ; AL = 14, AH = 2 ; 16位除法:AX = DX:AX ÷ 源, DX = 余数 mov dx, 0 mov ax, 10000 mov bx, 100 div bx ; AX = 100, DX = 0 ; 32位除法:EAX = EDX:EAX ÷ 源, EDX = 余数 mov edx, 0 ; 清零高位!重要! mov eax, 1000000 mov ebx, 7 div ebx ; EAX = 142857, EDX = 14.2 IDIV(有符号除法)
; IDIV 源 ; 有符号除法 ; 需要先扩展符号位 mov eax, -100 cdq ; 符号扩展EAX到EDX:EAX mov ebx, 7 idiv ebx ; EAX = -14, EDX = -2 ; 符号扩展指令: ; CBW - AL → AX ; CWD - AX → DX:AX ; CDQ - EAX → EDX:EAX ; CQO - RAX → RDX:RAX (x64)4.3 除法注意事项
除法异常(Divide Error,中断0)发生条件: 1. 除数为0 2. 商太大,无法存放 例如: mov ax, 0xFFFF ; AX = 65535 mov bl, 1 div bl ; 商65535,无法存入AL!异常! 预防方法: 1. 检查除数是否为0 2. 确保被除数不会太大5. 比较指令
; CMP 操作数1, 操作数2 ; 执行减法但不保存结果,只设置标志位 cmp eax, ebx ; 等价于 sub eax, ebx,但不改变EAX cmp eax, 0 ; 检查EAX是否为0 cmp [var], 100 ; 比较内存值 ; 通常后面跟条件跳转 cmp eax, 10 jg greater ; if eax > 10, jump jl less ; if eax < 10, jump je equal ; if eax == 10, jump6. 练习题
练习1:计算表达式(难度:★★☆☆☆)
计算 (15 + 7) * 3 - 10
练习2:除法求余(难度:★★☆☆☆)
计算 100 除以 7 的商和余数
练习3:64位加法(难度:★★★☆☆)
在32位模式下,计算两个64位数的和
7. 小结
[加法] 1. ADD - 普通加法 2. ADC - 带进位加法 3. INC - 加1(不影响CF) [减法] 4. SUB - 普通减法 5. SBB - 带借位减法 6. DEC - 减1(不影响CF) 7. NEG - 取负 [乘法] 8. MUL - 无符号乘法 9. IMUL - 有符号乘法 [除法] 10. DIV - 无符号除法 11. IDIV - 有符号除法 12. 商在EAX,余数在EDX [比较] 13. CMP - 比较(减法不保存)下一篇预告:Day 7 - 逻辑与位操作指令