🎬 HoRain云小助手个人主页

 🔥 个人专栏: 《Linux 系列教程》《c语言教程

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

专栏介绍

专栏名称

专栏介绍

《C语言》

本专栏主要撰写C干货内容和编程技巧,让大家从底层了解C,把更多的知识由抽象到简单通俗易懂。

《网络协议》

本专栏主要是注重从底层来给大家一步步剖析网络协议的奥秘,一起解密网络协议在运行中协议的基本运行机制!

《docker容器精解篇》

全面深入解析 docker 容器,从基础到进阶,涵盖原理、操作、实践案例,助您精通 docker。

《linux系列》

本专栏主要撰写Linux干货内容,从基础到进阶,知识由抽象到简单通俗易懂,帮你从新手小白到扫地僧。

《python 系列》

本专栏着重撰写Python相关的干货内容与编程技巧,助力大家从底层去认识Python,将更多复杂的知识由抽象转化为简单易懂的内容。

《试题库》

本专栏主要是发布一些考试和练习题库(涵盖软考、HCIE、HRCE、CCNA等)

目录

⛳️ 推荐

专栏介绍

📊 汇编语言 - 算术指令完全指南

1. 📋 目录

1. 📊 基本算术指令

1.1 ADD - 加法指令

1.2 SUB - 减法指令

1.3 INC/DEC - 递增/递减指令

2. 🔢 乘法和除法

2.1 MUL/IMUL - 乘法指令

2.2 DIV/IDIV - 除法指令

3. 🎯 位运算指令

3.1 逻辑位运算

4. 🔄 移位和循环指令

4.1 移位指令

5. 🏁 标志寄存器操作


img

📊 汇编语言 - 算术指令完全指南

算术指令是汇编语言中最基础和最重要的指令集之一,用于执行数学运算。让我们深入探讨各种算术指令的用法、工作原理和实际应用。

; ===================================================================
; 汇编语言算术指令完全指南
; 架构: x86/x86-64
; 示例使用NASM语法
; ===================================================================

1. 📋 目录

; ===================================================================
; 1. 📊 基本算术指令
;   1.1 ADD - 加法
;   1.2 SUB - 减法
;   1.3 INC - 递增
;   1.4 DEC - 递减
;   1.5 NEG - 取负
; 
; 2. 🔢 乘法和除法
;   2.1 MUL - 无符号乘法
;   2.2 IMUL - 有符号乘法
;   2.3 DIV - 无符号除法
;   2.4 IDIV - 有符号除法
;   2.5 CBW/CWDE/CDQE - 符号扩展
;   2.6 CWD/CDQ/CQO - 符号扩展
; 
; 3. 🎯 位运算指令
;   3.1 AND - 逻辑与
;   3.2 OR - 逻辑或
;   3.3 XOR - 逻辑异或
;   3.4 NOT - 逻辑非
;   3.5 TEST - 测试
; 
; 4. 🔄 移位和循环指令
;   4.1 SHL/SHR - 逻辑移位
;   4.2 SAL/SAR - 算术移位
;   4.3 ROL/ROR - 循环移位
;   4.4 RCL/RCR - 带进位循环移位
; 
; 5. 🏁 标志寄存器
;   5.1 状态标志
;   5.2 控制标志
;   5.3 条件跳转
; 
; 6. 🧮 扩展运算
;   6.1 ADC - 带进位加法
;   6.2 SBB - 带借位减法
;   6.3 XADD - 交换并相加
;   6.4 CMPXCHG - 比较并交换
; 
; 7. 📈 整数运算
;   7.1 扩展精度运算
;   7.2 BCD运算
;   7.3 十进制调整
; 
; 8. 🔧 浮点运算
;   8.1 FPU基本指令
;   8.2 SSE浮点运算
;   8.3 AVX浮点运算
; 
; 9. ⚡ 优化技巧
;   9.1 快速乘法技巧
;   9.2 除法优化
;   9.3 位运算技巧
; 
; 10. 🎪 实际应用
;   10.1 数学函数实现
;   10.2 加密算法
;   10.3 图形计算
; ===================================================================

1. 📊 基本算术指令

1.1 ADD - 加法指令

section .data
    num1    dd 100
    num2    dd 50
    result  dd 0

section .text
    global _start

_start:
    ; ============================================
    ; ADD 指令 - 加法
    ; 语法: ADD 目标操作数, 源操作数
    ; 功能: 目标操作数 = 目标操作数 + 源操作数
    ; 影响标志: OF, SF, ZF, AF, CF, PF
    ; ============================================
    
    ; 1.1 寄存器相加
    mov eax, 10
    mov ebx, 20
    add eax, ebx        ; eax = 10 + 20 = 30
    
    ; 1.2 寄存器与立即数相加
    add eax, 5          ; eax = 30 + 5 = 35
    
    ; 1.3 内存与寄存器相加
    mov dword [result], 100
    add dword [result], eax  ; [result] = 100 + 35 = 135
    
    ; 1.4 内存与立即数相加
    add dword [num1], 25     ; [num1] = 100 + 25 = 125
    
    ; 1.5 不同大小的操作数
    mov al, 200        ; 8位
    add al, 100        ; 进位到CF
    
    mov bx, 30000      ; 16位
    add bx, 40000      ; 可能产生进位
    
    mov ecx, 0xFFFFFFFF  ; 32位
    add ecx, 1           ; 产生进位,ecx = 0
    
    ; 1.6 多个数相加
    mov eax, 10
    add eax, 20         ; eax = 30
    add eax, 30         ; eax = 60
    add eax, 40         ; eax = 100
    
    ; 1.7 使用数组
    section .data
    array dd 1, 2, 3, 4, 5
    array_len equ ($ - array) / 4
    
    section .text
    mov esi, array
    mov ecx, array_len
    xor eax, eax        ; 清零eax,用于求和
    
sum_loop:
    add eax, [esi]      ; 累加数组元素
    add esi, 4          ; 移动到下一个元素
    loop sum_loop       ; ecx--,如果ecx != 0则跳转
    
    ; 此时 eax = 1+2+3+4+5 = 15
    
    ; 1.8 检测溢出
    mov al, 100
    add al, 28          ; 结果128 > 127(有符号8位最大值)
    ; 设置OF(溢出标志)和SF(符号标志)
    
    ; 检查是否溢出
    jo overflow_detected
    jmp no_overflow
    
overflow_detected:
    ; 处理溢出
    ; ...
    
no_overflow:
    ; 1.9 加法与标志位
    mov eax, 0x7FFFFFFF  ; 最大正有符号32位整数
    add eax, 1           ; 溢出到负数
    ; SF=1(负号), OF=1(溢出), ZF=0(非零)
    
    ; 1.10 清空寄存器技巧
    xor eax, eax         ; 比 mov eax, 0 更高效
    add eax, 10          ; eax = 10
    
    ; 1.11 自增技巧
    add eax, 1           ; 递增1
    ; 可以使用 inc eax,但 inc 不影响CF标志
    
    ; 1.12 大数加法(64位)
    ; 低32位
    mov eax, 0xFFFFFFFF
    mov ebx, 1
    add eax, ebx         ; eax = 0, CF=1
    
    ; 高32位(带进位)
    mov edx, 0
    adc edx, 0           ; edx = 1(如果有进位)
    ; 结果:edx:eax = 0x1:0x0 = 0x100000000
    
    ; 1.13 字符串数字相加
    section .data
    str_num1 db "12345", 0
    str_num2 db "67890", 0
    result_str db 10 dup(0)  ; 10字节缓冲区
    
    section .text
    ; 转换字符串为数字并相加
    call atoi
    ; 这里简化,实际需要转换函数
    
    ; 退出程序
    mov eax, 1          ; sys_exit
    xor ebx, ebx        ; 返回0
    int 0x80
    
atoi:
    ; 字符串转整数函数
    ; ...
    ret

1.2 SUB - 减法指令

section .text
    global _start

_start:
    ; ============================================
    ; SUB 指令 - 减法
    ; 语法: SUB 目标操作数, 源操作数
    ; 功能: 目标操作数 = 目标操作数 - 源操作数
    ; 影响标志: OF, SF, ZF, AF, CF, PF
    ; ============================================
    
    ; 2.1 基本减法
    mov eax, 100
    mov ebx, 30
    sub eax, ebx        ; eax = 100 - 30 = 70
    
    ; 2.2 立即数减法
    sub eax, 20         ; eax = 70 - 20 = 50
    
    ; 2.3 内存减法
    mov dword [result], 200
    sub dword [result], 50  ; [result] = 200 - 50 = 150
    
    ; 2.4 求相反数
    mov eax, 100
    neg eax             ; eax = -100
    add eax, 150        ; eax = 50
    
    ; 2.5 标志位检查
    mov al, 10
    sub al, 20          ; al = -10(有符号),246(无符号)
    ; CF=1(借位), SF=1(负号), OF=0(无溢出)
    
    ; 2.6 比较大小
    mov eax, 50
    mov ebx, 100
    sub eax, ebx        ; 比较eax和ebx
    jl  less_than       ; 如果eax < ebx则跳转
    jmp not_less
    
less_than:
    ; eax < ebx的情况
    ; ...
    
not_less:
    ; 2.7 清空寄存器
    sub eax, eax        ; eax = 0
    ; 比 mov eax, 0 更高效,但会设置标志位
    
    ; 2.8 减法溢出检测
    mov al, -128        ; 有符号8位最小值
    sub al, 1           ; 溢出到127
    ; OF=1(溢出), SF=0(正号)
    
    jo subtraction_overflow
    
subtraction_overflow:
    ; 处理减法溢出
    ; ...
    
    ; 2.9 大数减法(64位)
    ; 低32位
    mov eax, 0
    mov ebx, 1
    sub eax, ebx        ; eax = 0xFFFFFFFF, CF=1(借位)
    
    ; 高32位(带借位)
    mov edx, 0
    sbb edx, 0          ; edx = 0xFFFFFFFF(有借位)
    ; 结果:edx:eax = 0xFFFFFFFF:0xFFFFFFFF = -1
    
    ; 2.10 数组元素相减
    section .data
    numbers dd 100, 200, 300, 400, 500
    diff dd 0
    
    section .text
    mov esi, numbers
    mov eax, [esi+4]    ; 第二个元素
    sub eax, [esi]      ; 减去第一个元素
    mov [diff], eax     ; diff = 200 - 100 = 100
    
    ; 2.11 递减计数
    mov ecx, 10
countdown:
    ; 循环体
    ; ...
    sub ecx, 1          ; ecx--
    jnz countdown       ; 如果ecx != 0则继续
    
    ; 2.12 求绝对值
    mov eax, -100
    cmp eax, 0
    jge positive
    neg eax             ; 如果是负数,取反
    
positive:
    ; 此时eax包含绝对值
    
    ; 2.13 计算偏移量
    mov eax, buffer_end
    mov ebx, buffer_start
    sub eax, ebx        ; eax = 缓冲区大小
    
    ; 2.14 减法与加法结合
    mov eax, 100
    sub eax, 30         ; eax = 70
    add eax, 20         ; eax = 90
    sub eax, 10         ; eax = 80
    
    ; 2.15 使用LEA进行算术
    lea eax, [ebx + ecx*4 - 10]  ; eax = ebx + ecx*4 - 10
    ; 比多个add/sub更快
    
    ; 退出程序
    mov eax, 1
    xor ebx, ebx
    int 0x80

1.3 INC/DEC - 递增/递减指令

section .data
    counter dd 0
    index   dd 0

section .text
    global _start

_start:
    ; ============================================
    ; INC 指令 - 递增
    ; 语法: INC 目标操作数
    ; 功能: 目标操作数 = 目标操作数 + 1
    ; 影响标志: OF, SF, ZF, AF, PF
    ; 注意: INC 不影响 CF 标志!
    ; ============================================
    
    ; 3.1 INC 基本用法
    mov eax, 10
    inc eax             ; eax = 11
    
    inc byte [counter]  ; 8位内存递增
    inc word [counter]  ; 16位内存递增
    inc dword [counter] ; 32位内存递增
    
    ; 3.2 循环计数器
    mov ecx, 10
loop_start:
    ; 循环体
    inc byte [index]    ; 索引递增
    loop loop_start     ; ecx--, 如果ecx!=0则跳转
    
    ; 3.3 指针递增
    mov esi, buffer
    mov ecx, 100
copy_loop:
    mov al, [esi]
    ; 处理数据...
    inc esi             ; 移动到下一个字节
    loop copy_loop
    
    ; 3.4 数组遍历
    mov esi, array
    mov edi, dest_array
    mov ecx, array_size
array_copy:
    mov eax, [esi]
    mov [edi], eax
    add esi, 4          ; 32位数组,加4字节
    add edi, 4
    loop array_copy
    
    ; ============================================
    ; DEC 指令 - 递减
    ; 语法: DEC 目标操作数
    ; 功能: 目标操作数 = 目标操作数 - 1
    ; 影响标志: OF, SF, ZF, AF, PF
    ; 注意: DEC 不影响 CF 标志!
    ; ============================================
    
    ; 3.5 DEC 基本用法
    mov ebx, 20
    dec ebx             ; ebx = 19
    
    dec byte [counter]  ; 8位内存递减
    dec word [counter]  ; 16位内存递减
    dec dword [counter] ; 32位内存递减
    
    ; 3.6 递减循环
    mov ecx, 10
    dec ecx             ; ecx = 9
    jnz not_zero        ; 如果ecx != 0则跳转
    
    ; 3.7 倒计数
    mov ecx, 10
countdown_loop:
    ; 循环体,从10到1
    ; ...
    dec ecx
    jnz countdown_loop
    
    ; 3.8 指针递减
    mov edi, buffer_end
    mov ecx, 100
reverse_copy:
    dec edi             ; 移动到前一个字节
    mov al, [edi]
    ; 处理数据...
    loop reverse_copy
    
    ; 3.9 使用INC/DEC避免影响CF标志
    mov eax, 0xFFFFFFFF
    stc                 ; 设置CF=1
    inc eax             ; eax = 0, CF保持不变(仍为1)
    
    ; 对比ADD会改变CF
    mov eax, 0xFFFFFFFF
    stc                 ; 设置CF=1
    add eax, 1          ; eax = 0, CF=1(有进位)
    
    ; 3.10 循环展开中的INC/DEC
    mov ecx, 100
    mov esi, source
    mov edi, destination
    
unrolled_loop:
    ; 每次迭代处理4个元素
    mov eax, [esi]
    mov [edi], eax
    add esi, 4
    add edi, 4
    
    mov eax, [esi]
    mov [edi], eax
    add esi, 4
    add edi, 4
    
    mov eax, [esi]
    mov [edi], eax
    add esi, 4
    add edi, 4
    
    mov eax, [esi]
    mov [edi], eax
    add esi, 4
    add edi, 4
    
    sub ecx, 4          ; 处理了4个元素
    jnz unrolled_loop
    
    ; 3.11 边界检查
    mov ecx, array_size
    jecxz empty_array   ; 如果ecx=0则跳转
    
process_array:
    dec ecx
    js done             ; 如果ecx变为负数则完成
    
    ; 处理array[ecx]
    mov eax, [array + ecx*4]
    ; ...
    jmp process_array
    
empty_array:
    ; 数组为空的情况
    ; ...
    
done:
    ; 3.12 多精度递增
    ; 递增64位值
    add dword [low_dword], 1
    adc dword [high_dword], 0
    
    ; 使用INC(不影响CF)
    inc dword [low_dword]
    jnz no_carry
    inc dword [high_dword]
no_carry:
    
    ; 3.13 性能考虑
    ; INC/DEC 在大多数现代CPU上与ADD/SUB同样快
    ; 但INC/DEC不影响CF,有时很有用
    
    ; 退出程序
    mov eax, 1
    xor ebx, ebx
    int 0x80

section .bss
    buffer resb 100
    dest_array resd 100
    source resd 100
    destination resd 100
    array resd 100
    array_size equ 100
    low_dword resd 1
    high_dword resd 1

2. 🔢 乘法和除法

2.1 MUL/IMUL - 乘法指令

section .data
    ; 测试数据
    byte1   db 10
    byte2   db 20
    word1   dw 1000
    word2   dw 2000
    dword1  dd 100000
    dword2  dd 200000
    result8 dw 0      ; 8位乘法结果(16位)
    result16 dd 0     ; 16位乘法结果(32位)
    result32 dq 0     ; 32位乘法结果(64位)

section .text
    global _start

_start:
    ; ============================================
    ; MUL 指令 - 无符号乘法
    ; 语法: MUL 源操作数
    ; 8位:  AL * src8 → AX
    ; 16位: AX * src16 → DX:AX
    ; 32位: EAX * src32 → EDX:EAX
    ; 64位: RAX * src64 → RDX:RAX
    ; 影响标志: OF, CF(如果结果的高半部分为0则清除)
    ; ============================================
    
    ; 4.1 8位无符号乘法
    mov al, 10         ; AL = 10
    mov bl, 20         ; BL = 20
    mul bl             ; AX = AL * BL = 200
    mov [result8], ax  ; 保存结果
    
    ; 4.2 16位无符号乘法
    mov ax, 1000       ; AX = 1000
    mov bx, 2000       ; BX = 2000
    mul bx             ; DX:AX = AX * BX = 2,000,000
    ; DX = 高位字,AX = 低位字
    mov [result16], ax
    mov [result16+2], dx
    
    ; 4.3 32位无符号乘法
    mov eax, 100000    ; EAX = 100,000
    mov ebx, 200000    ; EBX = 200,000
    mul ebx            ; EDX:EAX = EAX * EBX = 20,000,000,000
    mov [result32], eax
    mov [result32+4], edx
    
    ; 4.4 大数乘法示例
    ; 计算 1234 * 5678
    mov ax, 1234
    mov bx, 5678
    mul bx             ; DX:AX = 1234 * 5678 = 7,006,652
    
    ; 4.5 检查溢出
    mov al, 100
    mov bl, 3
    mul bl             ; AX = 300, CF=OF=0(无溢出)
    
    mov al, 200
    mov bl, 2
    mul bl             ; AX = 400, CF=OF=1(溢出,AH != 0)
    
    ; 4.6 内存操作数
    mov al, [byte1]
    mul byte [byte2]   ; AL * [byte2] → AX
    
    mov ax, [word1]
    mul word [word2]   ; AX * [word2] → DX:AX
    
    ; ============================================
    ; IMUL 指令 - 有符号乘法
    ; 语法1: IMUL 源操作数(与MUL相同)
    ; 语法2: IMUL 目标, 源
    ; 语法3: IMUL 目标, 源, 立即数
    ; 影响标志: OF, CF(如果结果符合目标则清除)
    ; ============================================
    
    ; 4.7 单操作数形式(与MUL相同)
    mov al, -10        ; AL = -10(有符号)
    mov bl, 20         ; BL = 20
    imul bl            ; AX = -200
    ; 结果在AX中
    
    ; 4.8 双操作数形式
    mov eax, 100
    mov ebx, -3
    imul eax, ebx      ; EAX = EAX * EBX = -300
    
    imul eax, 5        ; EAX = EAX * 5 = -1500
    
    ; 4.9 三操作数形式
    imul eax, ebx, 10  ; EAX = EBX * 10
    
    ; 4.10 有符号乘法示例
    ; 计算 (-123) * 456
    mov eax, -123
    mov ebx, 456
    imul ebx           ; EDX:EAX = -123 * 456 = -56,088
    
    ; 4.11 检查有符号溢出
    mov al, 100
    mov bl, 2
    imul bl            ; AX = 200, OF=0(无溢出)
    
    mov al, 100
    mov bl, 3
    imul bl            ; AX = 300, OF=1(溢出)
    
    ; 4.12 使用IMUL进行快速乘法
    ; 乘以常数(使用移位和加法)
    mov eax, 123
    imul eax, 9        ; EAX = 123 * 9
    ; 编译为: eax * 8 + eax = 984 + 123 = 1107
    
    ; 乘以5: eax * 4 + eax
    ; 乘以10: eax * 8 + eax * 2
    
    ; 4.13 扩展精度乘法
    ; 计算64位 * 64位 → 128位
    ; 假设我们要计算 a*b,其中a和b是64位数
    ; a存储在 EDX:EAX, b存储在 ECX:EBX
    ; 结果存储在 内存中
    
section .data
    a_high dd 0x00000001
    a_low  dd 0x23456789
    b_high dd 0x00000001
    b_low  dd 0xABCDEF01
    
section .text
    ; 加载a
    mov eax, [a_low]
    mov edx, [a_high]
    
    ; 加载b
    mov ebx, [b_low]
    mov ecx, [b_high]
    
    ; 计算 a_low * b_low
    mul ebx            ; EDX:EAX = EAX * EBX
    
    ; 保存低64位结果
    mov [result64_low], eax
    mov [result64_low+4], edx
    
    ; 计算 a_high * b_low
    mov eax, [a_high]
    mul ebx            ; EDX:EAX = a_high * b_low
    
    ; 计算 a_low * b_high
    mov ebx, [b_high]
    mov ecx, eax       ; 保存中间结果
    mov eax, [a_low]
    mul ebx            ; EDX:EAX = a_low * b_high
    
    ; 相加得到高64位
    add eax, [result64_low+4]  ; 加上之前的进位
    adc edx, 0
    add eax, ecx       ; 加上a_high*b_low的结果
    adc edx, 0
    
    ; 保存高64位结果
    mov [result64_high], eax
    mov [result64_high+4], edx
    
    ; 4.14 乘法表生成
    mov ecx, 10        ; 行数
    mov ebx, 1         ; 当前行
    
multiplication_table:
    push ecx
    mov ecx, 10        ; 列数
    mov eax, 1         ; 当前列
    
inner_loop:
    ; 计算 eax * ebx
    imul eax, ebx
    ; 这里可以输出结果...
    inc eax
    loop inner_loop
    
    pop ecx
    inc ebx
    loop multiplication_table
    
    ; 4.15 矩阵乘法示例
    ; 计算 C = A * B
    ; 其中A是m×n矩阵,B是n×p矩阵
    
section .data
    ; 简单示例: 2x2矩阵
    matrix_a dd 1, 2, 3, 4    ; 2x2矩阵
    matrix_b dd 5, 6, 7, 8    ; 2x2矩阵
    matrix_c dd 0, 0, 0, 0    ; 结果矩阵
    
section .text
    ; 计算矩阵乘法
    ; C[0,0] = A[0,0]*B[0,0] + A[0,1]*B[1,0]
    mov eax, [matrix_a]       ; A[0,0]
    imul eax, [matrix_b]      ; * B[0,0]
    mov ebx, eax
    
    mov eax, [matrix_a+4]     ; A[0,1]
    imul eax, [matrix_b+8]    ; * B[1,0]
    add ebx, eax
    mov [matrix_c], ebx       ; C[0,0]
    
    ; 类似计算其他元素...
    
    ; 4.16 性能优化技巧
    ; 使用LEA进行快速乘以小常数
    mov eax, 123
    lea eax, [eax + eax*2]    ; eax = eax * 3
    lea eax, [eax*4]          ; eax = eax * 4
    lea eax, [eax + eax*4]    ; eax = eax * 5
    
    ; 乘以常数9: eax * 8 + eax
    mov ebx, eax
    shl eax, 3                ; eax * 8
    add eax, ebx              ; + eax
    
    ; 退出程序
    mov eax, 1
    xor ebx, ebx
    int 0x80

section .bss
    result64_low resd 2
    result64_high resd 2

2.2 DIV/IDIV - 除法指令

section .data
    ; 测试数据
    dividend32 dd 100
    divisor32  dd 7
    quotient32 dd 0
    remainder32 dd 0
    
    dividend64 dq 1000
    divisor64  dd 7
    quotient64 dd 0
    remainder64 dd 0
    
    dividend_neg dd -100
    divisor_neg  dd 7
    
    ; 用于扩展精度除法的数据
    dividend128 dq 0x12345678, 0x9ABCDEF0  ; 128位被除数
    divisor64_single dd 0x1000              ; 32位除数

section .text
    global _start

_start:
    ; ============================================
    ; DIV 指令 - 无符号除法
    ; 语法: DIV 除数
    ; 8位:  AX / src8 → AL=商, AH=余数
    ; 16位: DX:AX / src16 → AX=商, DX=余数
    ; 32位: EDX:EAX / src32 → EAX=商, EDX=余数
    ; 64位: RDX:RAX / src64 → RAX=商, RDX=余数
    ; 注意: 如果商溢出(>目标寄存器容量)会触发除法错误
    ; ============================================
    
    ; 5.1 8位无符号除法
    mov ax, 100        ; AX = 100
    mov bl, 7          ; BL = 7
    div bl             ; AL = 14, AH = 2
    ; 商: AL = 100/7 = 14
    ; 余数: AH = 100%7 = 2
    
    ; 5.2 16位无符号除法
    mov dx, 0          ; 高16位清零
    mov ax, 1000       ; 低16位
    mov bx, 7
    div bx             ; AX = 142, DX = 6
    
    ; 5.3 32位无符号除法
    mov edx, 0         ; 高32位清零
    mov eax, 100       ; 低32位
    mov ebx, 7
    div ebx            ; EAX = 14, EDX = 2
    
    mov [quotient32], eax
    mov [remainder32], edx
    
    ; 5.4 64位无符号除法(32位模式下)
    ; 被除数在EDX:EAX,除数是32位
    mov edx, 0x00000001  ; 高32位 = 1
    mov eax, 0x00000000  ; 低32位 = 0
    ; 总共: 0x100000000 = 4294967296
    mov ebx, 1000000000  ; 除数 = 1,000,000,000
    div ebx             ; EAX = 4, EDX = 294967296
    
    ; 5.5 检查除法错误
    mov ax, 1000
    mov bl, 0          ; 除数为零!
    ; div bl           ; 这会触发除法错误(中断0)
    ; 需要先检查除数
    test bl, bl
    jz division_error
    
    ; 5.6 处理大被除数
    ; 被除数超过16位
    mov ax, 0xFFFF     ; AX = 65535
    add ax, 1          ; AX = 0, CF=1
    ; 需要处理进位
    jc handle_carry
    
    ; ============================================
    ; IDIV 指令 - 有符号除法
    ; 语法: IDIV 除数
    ; 格式与DIV相同,但处理有符号数
    ; 余数的符号与被除数相同
    ; ============================================
    
    ; 5.7 8位有符号除法
    mov ax, -100       ; AX = -100
    cwd                ; 扩展AX到DX:AX
    mov bx, 7
    idiv bx            ; AX = -14, DX = -2
    
    ; 5.8 32位有符号除法
    mov eax, -100
    cdq                ; 扩展EAX到EDX:EAX
    mov ebx, 7
    idiv ebx           ; EAX = -14, EDX = -2
    
    ; 5.9 有符号除法示例
    mov eax, 100
    mov ebx, -7
    cdq                ; 扩展EAX到EDX:EAX
    idiv ebx           ; EAX = -14, EDX = 2
    
    ; 5.10 符号扩展指令
    ; CBW: 扩展AL到AX
    ; CWD: 扩展AX到DX:AX
    ; CWDE: 扩展AX到EAX
    ; CDQ: 扩展EAX到EDX:EAX
    
    mov al, -5
    cbw                ; AX = 0xFFFB (-5)
    
    mov ax, -1000
    cwd                ; DX:AX = 0xFFFF:0xFC18 (-1000)
    
    mov eax, -100000
    cdq                ; EDX:EAX = 0xFFFFFFFF:0xFFFE7960 (-100000)
    
    ; 5.11 扩展精度除法
    ; 128位 ÷ 64位 = 64位商,64位余数
    ; 在32位模式下模拟
    
    ; 被除数: EDX:ECX:EBX:EAX (128位)
    ; 除数: 内存中的64位数
    
    ; 5.12 除法优化技巧
    ; 除以常数2的幂可以使用移位
    mov eax, 100
    shr eax, 1         ; eax = 50 (除以2)
    
    ; 除以非2的幂常数
    ; 编译器会使用魔术数乘法优化
    
    ; 5.13 计算模运算
    mov eax, 100
    mov ebx, 7
    xor edx, edx       ; 清零EDX
    div ebx            ; EAX=商, EDX=余数
    ; EDX包含 100 mod 7 = 2
    
    ; 5.14 同时获取商和余数
    mov eax, 12345
    mov ebx, 100
    xor edx, edx
    div ebx
    ; EAX = 123 (商)
    ; EDX = 45 (余数)
    
    ; 5.15 浮点转整数除法
    ; 计算 eax = (eax * 100) / divisor
    mov ebx, 100
    imul eax, ebx      ; eax = eax * 100
    cdq                ; 扩展到EDX:EAX
    idiv dword [divisor32] ; 除以除数
    
    ; 5.16 检查除法溢出
    ; 对于有符号除法,最大负数除以-1会溢出
    mov eax, 0x80000000 ; 最小有符号32位数
    mov ebx, -1
    cdq
    idiv ebx           ; 会溢出!
    
    ; 安全检查
    cmp eax, 0x80000000
    jne safe_divide
    cmp ebx, -1
    jne safe_divide
    ; 处理溢出情况
    
safe_divide:
    ; 正常除法
    
    ; 5.17 使用除法计算平均值
    mov eax, 100
    add eax, 200
    add eax, 300       ; 总和 = 600
    mov ebx, 3
    xor edx, edx
    div ebx            ; 平均值 = 200
    
    ; 5.18 百分比计算
    ; 计算 (value * 100) / total
    mov eax, 75        ; 值
    mov ebx, 100       ; 百分比基数
    imul eax, ebx      ; eax = 7500
    mov ebx, 150       ; 总量
    xor edx, edx
    div ebx            ; 百分比 = 50
    
    ; 5.19 大数除法示例
    ; 实现128位 ÷ 64位除法
section .bss
    dividend_hi resd 2
    dividend_lo resd 2
    divisor_64  resd 2
    quotient_64 resd 2
    remainder_64 resd 2

section .text
    ; 伪代码实现
    ; 这需要多次移位和减法操作
    ; 实际实现较复杂,这里展示概念
    
    ; 5.20 除法错误处理
    jmp division_end
    
division_error:
    ; 处理除数为零的情况
    mov eax, 0xFFFFFFFF  ; 返回错误值
    mov edx, 0xFFFFFFFF
    ; 或者跳转到错误处理程序
    
handle_carry:
    ; 处理进位的大数除法
    ; ...
    
    ; 5.21 使用AAM指令(ASCII调整)
    ; 用于BCD除法后调整
    mov ax, 0105h      ; AX = 105 (BCD)
    aam                ; AH = 1, AL = 5
    
division_end:
    ; 退出程序
    mov eax, 1
    xor ebx, ebx
    int 0x80

3. 🎯 位运算指令

3.1 逻辑位运算

section .data
    ; 测试数据
    test_byte  db 0b10101010
    test_dword dd 0x12345678
    mask       dd 0x0000FFFF
    flags      dd 0
    
    ; 位掩码常量
    FLAG_A equ 0x00000001
    FLAG_B equ 0x00000002
    FLAG_C equ 0x00000004
    FLAG_D equ 0x00000008
    FLAG_ALL equ FLAG_A | FLAG_B | FLAG_C | FLAG_D

section .text
    global _start

_start:
    ; ============================================
    ; AND 指令 - 逻辑与
    ; 语法: AND 目标, 源
    ; 功能: 目标 = 目标 & 源
    ; 影响标志: OF=0, CF=0, SF, ZF, PF
    ; ============================================
    
    ; 6.1 AND 基本用法
    mov eax, 0b11001100
    mov ebx, 0b10101010
    and eax, ebx       ; EAX = 0b10001000
    
    ; 6.2 清零特定位
    mov eax, 0xFF
    and eax, 0xF0      ; 清零低4位: EAX = 0xF0
    
    ; 6.3 检查奇偶性
    mov eax, 123
    test eax, 1        ; 检查最低位
    jnz odd_number     ; 如果ZF=0(位1),则是奇数
    
    ; 6.4 提取特定位
    mov eax, 0x12345678
    and eax, 0x0000FFFF ; 提取低16位: EAX = 0x5678
    
    ; 6.5 掩码操作
    mov eax, [flags]
    and eax, FLAG_A    ; 检查FLAG_A是否设置
    jnz flag_a_set
    
    ; ============================================
    ; OR 指令 - 逻辑或
    ; 语法: OR 目标, 源
    ; 功能: 目标 = 目标 | 源
    ; 影响标志: OF=0, CF=0, SF, ZF, PF
    ; ============================================
    
    ; 6.6 OR 基本用法
    mov eax, 0b11001100
    mov ebx, 0b00110011
    or eax, ebx        ; EAX = 0b11111111
    
    ; 6.7 设置特定位
    mov eax, [flags]
    or eax, FLAG_A     ; 设置FLAG_A
    or eax, FLAG_B     ; 设置FLAG_B
    mov [flags], eax
    
    ; 6.8 合并位域
    mov eax, 0x1200
    mov ebx, 0x0034
    or eax, ebx        ; EAX = 0x1234
    
    ; ============================================
    ; XOR 指令 - 逻辑异或
    ; 语法: XOR 目标, 源
    ; 功能: 目标 = 目标 ^ 源
    ; 影响标志: OF=0, CF=0, SF, ZF, PF
    ; ============================================
    
    ; 6.9 XOR 基本用法
    mov eax, 0b11001100
    mov ebx, 0b10101010
    xor eax, ebx       ; EAX = 0b01100110
    
    ; 6.10 清零寄存器
    xor eax, eax       ; EAX = 0,比mov eax, 0更快
    
    ; 6.11 切换位状态
    mov eax, [flags]
    xor eax, FLAG_A    ; 切换FLAG_A状态
    mov [flags], eax
    
    ; 6.12 交换值(不使用临时变量)
    mov eax, 10
    mov ebx, 20
    xor eax, ebx       ; EAX = 10 ^ 20
    xor ebx, eax       ; EBX = 20 ^ (10 ^ 20) = 10
    xor eax, ebx       ; EAX = (10 ^ 20) ^ 10 = 20
    
    ; 6.13 简单加密/解密
    mov eax, 0x12345678
    mov ebx, 0x9ABCDEF0  ; 密钥
    xor eax, ebx       ; 加密
    xor eax, ebx       ; 再次XOR解密
    
    ; ============================================
    ; NOT 指令 - 逻辑非
    ; 语法: NOT 目标
    ; 功能: 目标 = ~目标
    ; 不影响标志位!
    ; ============================================
    
    ; 6.14 NOT 基本用法
    mov eax, 0b11001100
    not eax            ; EAX = 0b00110011
    
    ; 6.15 求补码(负值)
    mov eax, 42
    not eax
    inc eax            ; EAX = -42
    
    ; 6.16 位反转
    mov eax, 0x0000FFFF
    not eax            ; EAX = 0xFFFF0000
    
    ; ============================================
    ; TEST 指令 - 测试
    ; 语法: TEST 目标, 源
    ; 功能: 目标 & 源,只设置标志位
    ; 影响标志: OF=0, CF=0, SF, ZF, PF
    ; ============================================
    
    ; 6.17 TEST 基本用法
    mov eax, 0b00001000
    test eax, 0b00001000
    jnz bit_set        ; 如果位3设置则跳转
    
    ; 6.18 测试多个位
    test eax, FLAG_A | FLAG_B
    jnz either_flag_set
    
    ; 6.19 测试零值
    test eax, eax
    jz is_zero
    
    ; 6.20 检查符号
    test eax, 0x80000000
    jnz is_negative
    
    ; 6.21 位操作应用示例
    
    ; 示例1: 设置位掩码
    mov eax, 0
    bts eax, 3         ; 设置位3(如果可用)
    or eax, 1 << 3     ; 设置位3的替代方法
    
    ; 示例2: 清除位掩码
    and eax, ~(1 << 3) ; 清除位3
    
    ; 示例3: 切换位掩码
    xor eax, 1 << 3    ; 切换位3
    
    ; 示例4: 检查位掩码
    test eax, 1 << 3
    jnz bit_3_set
    
    ; 示例5: 提取位域
    mov eax, 0x12345678
    and eax, 0x0000FF00 ; 提取字节1
    shr eax, 8         ; 右移8位
    
    ; 示例6: 插入位域
    mov eax, 0x12345678
    and eax, 0xFFFF00FF ; 清除字节1
    mov ebx, 0x99
    shl ebx, 8
    or eax, ebx        ; 设置字节1为0x99
    
    ; 示例7: 位计数(popcount)
    mov eax, 0b10101010
    xor ecx, ecx       ; 计数器清零
    
count_bits:
    test eax, eax
    jz count_done
    shr eax, 1
    adc ecx, 0         ; 如果CF=1则加1
    jmp count_bits
    
count_done:
    ; ECX包含位数
    
    ; 示例8: 查找最低有效位1
    mov eax, 0b00010100
    bsf ecx, eax       ; ECX = 2(位2是第一个1)
    ; 如果没有BSF指令:
    mov ebx, eax
    dec ebx
    not eax
    and eax, ebx       ; 清除最低有效位1
    
    ; 示例9: 交换字节序
    mov eax, 0x12345678
    bswap eax          ; EAX = 0x78563412
    
    ; 示例10: 位反转(没有专用指令时)
    mov eax, 0b11001100
    mov ecx, 32        ; 32位反转
    
reverse_bits:
    rcr eax, 1         ; 右移,最低位到CF
    rcl ebx, 1         ; 左移,CF到最低位
    loop reverse_bits
    
    ; 6.22 标志位操作
    ; 保存和恢复标志位
    pushf              ; 保存标志寄存器
    ; ... 修改标志位 ...
    popf               ; 恢复标志寄存器
    
    ; 设置/清除特定标志
    clc                ; 清除CF
    stc                ; 设置CF
    cmc               ; 取反CF
    
    cli               ; 清除IF(中断标志)
    sti              ; 设置IF
    
    cld              ; 清除DF(方向标志)
    std              ; 设置DF
    
    ; 6.23 条件码操作
    ; 根据标志设置字节
    mov al, 0
    setc al           ; 如果CF=1则AL=1
    setz al           ; 如果ZF=1则AL=1
    sets al           ; 如果SF=1则AL=1
    seto al           ; 如果OF=1则AL=1
    
    ; 6.24 位域操作
    ; 提取位5-8
    mov eax, 0x12345678
    shr eax, 5
    and eax, 0xF      ; 位5-8
    
    ; 插入位5-8
    mov ebx, 0x9
    shl ebx, 5
    and eax, ~(0xF << 5) ; 清除位5-8
    or eax, ebx       ; 设置新值
    
    ; 6.25 位图操作
    ; 设置位图中的位
    mov edi, bitmap
    mov eax, 42       ; 位索引
    mov ebx, eax
    shr eax, 5        ; 计算字节偏移
    and ebx, 0x1F     ; 计算位偏移
    bts [edi + eax*4], ebx ; 设置位
    
    ; 6.26 位运算优化技巧
    ; 乘以2的幂
    mov eax, 10
    shl eax, 1        ; 乘以2
    shl eax, 2        ; 乘以4
    shl eax, 3        ; 乘以8
    
    ; 除以2的幂
    mov eax, 100
    shr eax, 1        ; 除以2
    sar eax, 1        ; 有符号除以2
    
    ; 检查是否是2的幂
    mov eax, 64
    dec eax
    test eax, 64
    jz is_power_of_two
    
    ; 6.27 位运算实际应用
    
    ; 应用1: 权限系统
    %define PERM_READ   0x01
    %define PERM_WRITE  0x02
    %define PERM_EXEC   0x04
    %define PERM_ALL    PERM_READ | PERM_WRITE | PERM_EXEC
    
    mov eax, PERM_READ | PERM_WRITE
    test eax, PERM_READ
    jnz has_read_perm
    
    ; 应用2: 选项处理
    %define OPT_A 0x01
    %define OPT_B 0x02
    %define OPT_C 0x04
    
    mov ebx, OPT_A | OPT_C
    test ebx, OPT_A
    jnz option_a_enabled
    
    ; 应用3: 错误码
    %define ERR_NONE    0x00
    %define ERR_IO      0x01
    %define ERR_MEM     0x02
    %define ERR_INVALID 0x04
    
    mov ecx, ERR_IO | ERR_MEM
    test ecx, ERR_IO
    jnz io_error
    
    ; 退出程序
    mov eax, 1
    xor ebx, ebx
    int 0x80
    
    ; 标签定义
odd_number:
flag_a_set:
either_flag_set:
is_zero:
is_negative:
bit_3_set:
is_power_of_two:
has_read_perm:
option_a_enabled:
io_error:
    ; 错误处理代码
    ; ...

section .bss
    bitmap resd 256  ; 256个双字 = 8192位

4. 🔄 移位和循环指令

4.1 移位指令

section .data
    test_value dd 0x12345678
    shift_count db 4
    
    ; 测试模式
    bit_pattern dd 0b10101010101010101010101010101010
    signed_val dd -100
    unsigned_val dd 100

section .text
    global _start

_start:
    ; ============================================
    ; 移位指令
    ; 语法: SHL/SHR/SAL/SAR 目标, 计数
    ; 计数: 立即数或CL寄存器
    ; 影响标志: OF, SF, ZF, AF, PF, CF
    ; ============================================
    
    ; 7.1 SHL - 逻辑左移
    ; 向左移位,最低位补0,最高位移入CF
    mov eax, 0b00010001
    shl eax, 1         ; EAX = 0b00100010, CF = 0
    
    ; 7.2 SHR - 逻辑右移
    ; 向右移位,最高位补0,最低位移入CF
    mov eax, 0b10001000
    shr eax, 1         ; EAX = 0b01000100, CF = 0
    
    ; 7.3 SAL - 算术左移(与SHL相同)
    ; 向左移位,最低位补0,最高位移入CF
    mov eax, 0b00010001
    sal eax, 1         ; 同SHL
    
    ; 7.4 SAR - 算术右移
    ; 向右移位,最高位用符号位填充,最低位移入CF
    mov eax, -8         ; 0xFFFFFFF8
    sar eax, 1         ; EAX = -4 (0xFFFFFFFC), CF = 0
    
    mov ebx, 8
    sar ebx, 1         ; EBX = 4, CF = 0
    
    ; 7.5 使用CL作为移位计数
    mov cl, 3
    mov eax, 0x11111111
    shl eax, cl        ; EAX = 0x88888888
    
    ; 7.6 超过31的移位
    mov cl, 33
    mov eax, 0xFFFFFFFF
    shr eax, cl        ; 实际移位33 & 31 = 1位
    
    ; 7.7 移位应用:乘以2的幂
    mov eax, 5
    shl eax, 1         ; 乘以2: 10
    shl eax, 2         ; 乘以4: 40
    shl eax, 3         ; 乘以8: 320
    
    ; 7.8 移位应用:除以2的幂
    mov eax, 100
    shr eax, 1         ; 无符号除以2: 50
    sar eax, 2         ; 有符号除以4: 12
    
    ; 7.9 移位应用:提取位域
    mov eax, 0x12345678
    ; 提取位16-23
    shr eax, 16
    and eax, 0xFF      ; EAX = 0x34
    
    ; 7.10 移位应用:组合位域
    mov eax, 0x1200
    mov ebx, 0x0034
    shl eax, 8
    or eax, ebx        ; EAX = 0x1234
    
    ; 7.11 移位应用:位反转
    mov eax, 0b11001100
    mov ecx, 8
    xor ebx, ebx
    
reverse_bits_loop:
    shr eax, 1         ; 最低位到CF
    rcl ebx, 1         ; CF到最高位
    loop reverse_bits_loop
    
    ; 7.12 移位应用:乘法优化
    ; 乘以3: x*2 + x
    mov eax, 10
    mov ebx, eax
    shl eax, 1         ; x*2
    add eax, ebx       ; +x
    
    ; 乘以5: x*4 + x
    mov eax, 10
    mov ebx, eax
    shl eax, 2         ; x*4
    add eax, ebx       ; +x
    
    ; 乘以10: x*8 + x*2
    mov eax, 10
    mov ebx, eax
    shl eax, 3         ; x*8
    shl ebx, 1         ; x*2
    add eax, ebx
    
    ; ============================================
    ; 循环移位指令
    ; 语法: ROL/ROR/RCL/RCR 目标, 计数
    ; 影响标志: OF, CF
    ; ============================================
    
    ; 7.13 ROL - 循环左移
    ; 向左循环移位,最高位移到CF和最低位
    mov eax, 0b10001000
    rol eax, 1         ; EAX = 0b00010001, CF = 1
    
    ; 7.14 ROR - 循环右移
    ; 向右循环移位,最低位移到CF和最高位
    mov eax, 0b10001000
    ror eax, 1         ; EAX = 0b01000100, CF = 0
    
    ; 7.15 RCL - 带进位循环左移
    ; 向左循环移位,通过CF
    clc                ; CF = 0
    mov eax, 0b10001000
    rcl eax, 1         ; EAX = 0b00010000, CF = 1
    
    ; 7.16 RCR - 带进位循环右移
    ; 向右循环移位,通过CF
    stc                ; CF = 1
    mov eax, 0b10001000
    rcr eax, 1         ; EAX = 0b11000100, CF = 0
    
    ; 7.17 循环移位应用:位旋转加密
    mov eax, 0x12345678
    mov cl, 4
    rol eax, cl        ; 左旋转4位
    
    ; 解密
    ror eax, cl        ; 右旋转4位
    
    ; 7.18 循环移位应用:检查位
    mov eax, 0b00001000
    mov ecx, 32
    
check_all_bits:
    rcl eax, 1         ; 最高位到CF
    jc bit_is_set
    loop check_all_bits
    
    ; 7.19 移位标志位
    ; SHL/SAL: 如果符号改变,OF=1
    ; SHR: 如果移位前最高位是1,OF=1
    ; SAR: OF=0
    ; ROL/ROR: 如果符号改变,OF=1
    ; RCL/RCR: 复杂...
    
    ; 7.20 双精度移位
    ; SHLD - 双精度左移
    ; SHRD - 双精度右移
    
    mov eax, 0x12345678
    mov ebx, 0x9ABCDEF0
    mov cl, 4
    
    shld ebx, eax, cl  ; EBX左移,从EAX移入位
    shrd eax, ebx, cl  ; EAX右移,从EBX移入位
    
    ; 7.21 移位与条件
    ; 检查第n位
    mov eax, 0x12345678
    bt eax, 3          ; 检查位3,结果在CF
    jc bit_3_set_2
    
    ; 设置第n位
    bts eax, 3         ; 设置位3
    
    ; 清除第n位
    btr eax, 3         ; 清除位3
    
    ; 切换第n位
    btc eax, 3         ; 切换位3
    
    ; 7.22 位扫描
    ; BSF - 向前位扫描
    ; BSR - 向后位扫描
    
    mov eax, 0b00001000
    bsf ecx, eax       ; ECX = 3(最低设置位)
    bsr edx, eax       ; EDX = 3(最高设置位)
    
    ; 7.23 移位应用:浮点数操作
    ; 提取浮点数指数
    mov eax, 0x40A00000  ; 5.0的浮点表示
    shr eax, 23
    and eax, 0xFF       ; 指数
    
    ; 7.24 移位应用:BCD转换
    ; 二进制转BCD
    mov eax, 123
    mov ecx, 0
    mov ebx, 10
    
bin_to_bcd:
    xor edx, edx
    div ebx            ; EDX=余数, EAX=商
    shl edx, cl
    or ecx, edx
    add cl, 4
    test eax, eax
    jnz bin_to_bcd
    
    ; 7.25 移位应用:CRC计算
    mov eax, 0xFFFFFFFF  ; CRC初始值
    mov ecx, 32
    mov edx, 0xEDB88320  ; CRC32多项式
    
crc_loop:
    shr eax, 1
    jnc no_xor
    xor eax, edx
no_xor:
    loop crc_loop
    
    ; 7.26 移位应用:乘法(不使用MUL)
    ; 俄罗斯农民乘法算法
    mov eax, 13         ; 被乘数
    mov ebx, 9          ; 乘数
    xor ecx, ecx       ; 结果
    
russian_peasant:
    test ebx, 1
    jz skip_add
    add ecx, eax
skip_add:
    shl eax, 1         ; 被乘数翻倍
    shr ebx, 1         ; 乘数减半
    jnz russian_peasant
    ; 结果在ECX中
    
    ; 7.27 移位应用:除法(不使用DIV)
    ; 恢复除法算法
    mov eax, 100       ; 被除数
    mov ebx, 7         ; 除数
    xor edx, edx       ; 余数
    mov ecx, 32        ; 循环计数
    
restoring_division:
    shl eax, 1         ; 左移被除数
    rcl edx, 1         ; 带进位左移余数
    
    ; 尝试减法
    sub edx, ebx
    jnc subtraction_ok
    add edx, ebx       ; 恢复
    clc
    jmp next_bit
subtraction_ok:
    stc
next_bit:
    rcl eax, 1         ; 商位
    loop restoring_division
    ; 商在EAX,余数在EDX
    
    ; 7.28 移位应用:位图操作
    ; 设置位图中的特定位
    mov edi, bitmap
    mov eax, 42         ; 位索引
    mov ebx, eax
    shr eax, 5          ; 计算双字索引
    and ebx, 0x1F       ; 计算位偏移
    bts [edi + eax*4], ebx  ; 设置位
    
    ; 7.29 移位应用:内存对齐
    ; 对齐到16字节边界
    mov eax, 0x1234567F
    add eax, 0x0F
    and eax, 0xFFFFFFF0
    
    ; 7.30 移位应用:颜色操作
    ; 提取RGB分量
    mov eax, 0x00FF00FF  ; ARGB颜色
    mov ebx, eax
    and eax, 0x00FF0000
    shr eax, 16         ; 红色分量
    mov ecx, ebx
    and ecx, 0x0000FF00
    shr ecx, 8          ; 绿色分量
    and ebx, 0x000000FF ; 蓝色分量
    
    ; 合并RGB分量
    shl eax, 16
    shl ecx, 8
    or eax, ecx
    or eax, ebx         ; 合并后的颜色
    
    ; 7.31 移位应用:浮点技巧
    ; 快速绝对值
    mov eax, -100
    cdq
    xor eax, edx
    sub eax, edx       ; EAX = |EAX|
    
    ; 快速最小值
    mov eax, 10
    mov ebx, 20
    sub eax, ebx
    sar eax, 31        ; 符号扩展
    and eax, ebx
    add eax, 10        ; EAX = min(10, 20)
    
    ; 退出程序
    mov eax, 1
    xor ebx, ebx
    int 0x80

bit_3_set_2:
    ; 处理代码
    ; ...

section .bss
    bitmap2 resd 256

5. 🏁 标志寄存器操作

section .data
    ; 测试数据
    test_num1 dd 100
    test_num2 dd 200
    result_flags dd 0
    
    ; 条件跳转测试
    compare_a dd 10
    compare_b dd 20
    
    ; 标志测试
    signed_a dd -10
    signed_b dd 20
    unsigned_a dd 0xFFFFFFF0  ; 4294967280
    unsigned_b dd 10

section .text
    global _start

_start:
    ; ============================================
    ; 标志寄存器 (EFLAGS) 重要位
    ; CF - 进位标志 (bit 0)
    ; PF - 奇偶标志 (bit 2)
    ; AF - 辅助进位标志 (bit 4)
    ; ZF - 零标志 (bit 6)
    ; SF - 符号标志 (bit 7)
    ; TF - 陷阱标志 (bit 8)
    ; IF - 中断允许标志 (bit 9)
    ; DF - 方向标志 (bit 10)
    ; OF - 溢出标志 (bit 11)
    ; ============================================
    
    ; 8.1 直接操作标志寄存器
    pushf               ; 将EFLAGS压栈
    pop eax             ; 弹出到EAX
    mov [result_flags], eax
    
    ; 设置标志
    push dword [result_flags]
    popf                ; 从堆栈设置EFLAGS
    
    ; 8.2 进位标志 (CF) 操作
    clc                 ; 清除CF
    stc                 ; 设置CF
    cmc                 ; 取反CF
    
    ; 使用ADC(带进位加法)
    mov eax, 0xFFFFFFFF
    mov ebx, 1
    add eax, ebx        ; EAX=0, CF=1
    adc edx, 0          ; EDX += CF
    
    ; 8.3 方向标志 (DF) 操作
    cld                 ; 清除DF(向前移动)
    std                 ; 设置DF(向后移动)
    
    ; 影响字符串操作
    cld
    mov esi, source
    mov edi, destination
    mov ecx, 100
    rep movsb          ; 从ESI复制到EDI,向前移动
    
    ; 8.4 测试CF标志
    mov al, 0xFF
    add al, 1          ; AL=0, CF=1
    jc carry_occurred
    
    mov al, 0x7F
    add al, 1          ; AL=0x80, CF=0, OF=1
    jo overflow_occurred
    
    ; 8.5 符号标志 (SF)
    mov eax, -10
    add eax, 5         ; EAX=-5, SF=1
    js negative_result
    
    mov eax, 10
    sub eax, 5         ; EAX=5, SF=0
    jns positive_result
    
    ; 8.6 零标志 (ZF)
    mov eax, 10
    sub eax, 10        ; EAX=0, ZF=1
    jz is_zero
    
    test eax, eax      ; 测试是否为0
    jz is_zero_2
    
    cmp eax, 0         ; 比较是否为0
    je is_zero_3
    
    ; 8.7 溢出标志 (OF)
    ; 有符号溢出检测
    mov al, 0x7F       ; 127
    add al, 1          ; AL=0x80 (-128), OF=1
    jo signed_overflow
    
    mov al, 0x80       ; -128
    sub al, 1         ; AL=0x7F (127), OF=1
    jo signed_overflow_2
    
    ; 8.8 奇偶标志 (PF)
    mov al, 0b00100111 ; 有偶数个1
    add al, 0         ; PF=1
    jp even_parity
    
    mov al, 0b00100110 ; 有奇数个1
    add al, 0         ; PF=0
    jnp odd_parity
    
    ; 8.9 辅助进位标志 (AF)
    ; 用于BCD运算
    mov al, 0x0F
    add al, 0x01      ; AF=1
    daa               ; 十进制调整
    
    ; 8.10 条件跳转指令
    ; 基于无符号比较
    mov eax, 100
    mov ebx, 200
    cmp eax, ebx
    
    ja  above          ; CF=0且ZF=0
    jae above_equal    ; CF=0
    jb  below          ; CF=1
    jbe below_equal    ; CF=1或ZF=1
    
    ; 基于有符号比较
    jg  greater        ; ZF=0且SF=OF
    jge greater_equal  ; SF=OF
    jl  less           ; SF≠OF
    jle less_equal     ; ZF=1或SF≠OF
    
    ; 基于标志
    jc  carry_set      ; CF=1
    jnc no_carry       ; CF=0
    jz  zero           ; ZF=1
    jnz not_zero       ; ZF=0
    js  sign_negative   ; SF=1
    jns sign_positive   ; SF=0
    jo  overflow        ; OF=1
    jno no_overflow    ; OF=0
    jp  parity_even    ; PF=1
    jnp parity_odd     ; PF=0
    
    ; 8.11 SETcc指令 - 根据条件设置字节
    cmp eax, ebx
    set

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐