计算机组成原理终极实验:用 ADD/INC 指令优化循环效率 300%

 引入

在计算机体系结构的金字塔中,加法指令是最接近硬件底层的 “原子操作” 之一。当你在高级语言中写下a + b时,编译器会将其翻译为ADD/ADC系列指令,而这些指令的每一个比特位设计,都藏着计算机科学的核心智慧:

  • 为什么 8086 架构规定操作数长度必须严格对齐?这背后是总线带宽与寄存器设计的工程妥协。
  • CFOF标志位的分野,本质是计算机对 “无符号数宇宙” 与 “有符号数宇宙” 的并行建模。
  • 从单周期INC到多精度ADC,指令集的进化史就是一部 “用有限硬件挑战无限数值” 的奋斗史。

本文将以 x86 汇编为例,拆解加法指令家族的 5 大核心成员(ADD/ADC/INC/AAA/DAA),通过 15 个实战案例、20 张标志位状态表、30 行可运行汇编代码,带你打通从 “指令手册记忆” 到 “底层机制顿悟” 的任督二脉。无论你是逆向工程师、操作系统开发者,还是想优化循环效率的 C/C++ 程序员,这里都有你需要的硬核知识。

一,ADD(加法指令):CPU 里的 “计算器”(超级细节版)

1. 功能拆解:谁加谁?加到哪?
  • 标准格式ADD 目标, 源
    • 目标:只能是 寄存器 或 内存(不能是立即数)。
    • :可以是 寄存器内存 或 立即数
  • 组合举例
    ADD AL, BL      ; 寄存器 + 寄存器 → AL = AL + BL
    ADD [NUM], 10   ; 内存 + 立即数 → [NUM] = [NUM] + 10
    ADD CX, [ADDR]  ; 寄存器 + 内存 → CX = CX + [ADDR]
    
2. 操作数长度必须匹配!
  • 错误案例
    MOV AL, 5       ; AL 是 8 位寄存器
    MOV BX, 1000    ; BX 是 16 位寄存器
    ADD AL, BX      ; 错误!8 位和 16 位不能直接相加
    
  • 正确做法:用相同长度的寄存器。
    MOV AX, 1000    ; AX 是 16 位
    ADD AX, BX      ; 正确!16 位 + 16 位
    
3. 进位(CF) vs 溢出(OF):彻底搞懂!
  • 进位(CF)

    • 无符号数运算时,结果超出寄存器最大值。
    • 例子
      MOV AL, 255     ; AL = 0xFF(无符号数 255)
      ADD AL, 1       ; AL = 0x00(255+1=256,超出 8 位范围)
                      ; CF = 1(表示向更高位进了 1)
      
  • 溢出(OF)

    • 有符号数运算时,结果超出表示范围。
    • 例子
      MOV AL, 120     ; AL = 0x78(有符号数 +120)
      ADD AL, 10      ; AL = 0x86(二进制 10000110,对应有符号数 -122)
                      ; OF = 1(因为 +120+10 本应得 +130,但 8 位有符号数最大是 +127)
      
4. 标志位全解析

ADD 会影响 6 个标志位:

标志位含义
CF进位标志。无符号数运算溢出时置 1(如 255+1 → CF=1)。
ZF零标志。结果为 0 时置 1(如 5+(-5)=0 → ZF=1)。
SF符号标志。结果为负数时置 1(有符号数视角)。
OF溢出标志。有符号数运算溢出时置 1(如 127+1 → OF=1)。
PF奇偶标志。结果的低 8 位中 1 的个数为偶数时置 1(如 0x0F → PF=0)。
AF辅助进位标志。低 4 位向高 4 位有进位时置 1(如 0x0F+1 → AF=1)。
5. 多字节加法:用 ADC 处理进位
  • 场景:计算超过寄存器长度的数(如 64 位加法)。
  • 步骤
    1. 用 ADD 加低位,产生的进位存入 CF。
    2. 用 ADC 加高位,并加上 CF。
  • 例子:计算 0x12345678 + 0x11111111(32 位加法)。
    MOV EAX, 0x5678      ; 低位 = 0x5678
    MOV EDX, 0x1234      ; 高位 = 0x1234
    MOV EBX, 0x11111111  ; 另一个 32 位数
    
    ADD EAX, EBX         ; 先加低位:0x5678 + 0x1111 = 0x6789
                         ; CF = 0(无进位)
    
    ADC EDX, 0           ; 再加高位:0x1234 + 0 + CF = 0x1234
                         ; 最终结果:[EDX:EAX] = 0x12346789
    
6. 生活类比:超市收银机
  • 寄存器:像收银机的显示屏,显示当前金额。
  • ADD 指令:相当于按 “+” 键。
    MOV AX, 100    ; 显示屏显示 100 元
    ADD AX, 50     ; 按“+”键,输入 50 → 显示屏变为 150 元
    
  • 进位(CF):当金额超过显示屏最大位数时,自动进位到更高位。
    MOV AL, 99     ; 显示屏(8 位)显示 99
    ADD AL, 1      ; 按“+”键,输入 1 → 显示屏变为 00,进位灯(CF)亮起
    
7. 常见错误清单
  1. 混用不同长度的操作数

    MOV AL, 5     ; AL 是 8 位
    ADD AL, 1000  ; 错误!1000 超过 8 位范围(0~255)
    
  2. 忘记处理进位

    MOV AX, 0xFFFF ; AX = 65535
    ADD AX, 1      ; AX = 0(溢出),CF=1
    ; 错误:没有保存进位,结果丢失最高位
    
  3. 误解标志位含义

    • CF 是无符号数的溢出,OF 是有符号数的溢出,两者可能同时出现或单独出现。
8. 一句话总结

ADD 是 CPU 的加法核心,但用它时要注意:

  1. 操作数长度要匹配(8 位和 16 位不能直接相加)。
  2. 区分进位(无符号溢出)和溢出(有符号溢出)
  3. 多字节加法要用 ADC 处理进位

二,ADC(带进位加法):多位数值加法的 “接力选手”

1. 功能:在 ADD 基础上,再加一个进位值(CF)
  • 公式目标 = 目标 + 源 + CF
    比如 ADC AX, BX 就是让 AX = AX + BX + CF
  • 存在意义:处理超过单个寄存器长度的大数加法(如 64 位、128 位)。
2. 为什么需要 ADC?
  • 单寄存器加法的局限
    例如 16 位寄存器 AX 最大只能存 65535(0xFFFF),如果要计算 65536 + 1,直接用 ADD 会溢出:

    MOV AX, 0xFFFF  ; AX = 65535
    ADD AX, 1       ; AX = 0(溢出),CF = 1(进位丢失!)
    
  • ADC 的作用:保存进位到更高位寄存器。

    MOV AX, 0xFFFF  ; AX = 65535
    MOV DX, 0       ; DX = 0(用于存高位)
    
    ADD AX, 1       ; AX = 0,CF = 1(低位加法产生进位)
    ADC DX, 0       ; DX = 0 + 0 + CF = 1(高位加上进位)
    ; 最终结果:[DX:AX] = 0x00010000(即 65536)
    
3. 操作数规则与 ADD 完全相同
  • 支持的组合
    ADC AL, BL      ; 寄存器 + 寄存器 + CF → AL
    ADC [NUM], 10   ; 内存 + 立即数 + CF → [NUM]
    ADC CX, [ADDR]  ; 寄存器 + 内存 + CF → CX
    
  • 长度要求:操作数必须长度匹配(如 8 位 + 8 位,16 位 + 16 位)。
4. 进位(CF)的传递机制
  • 每一步加法都会更新 CF
    ADC 执行后,新的进位会重新存入 CF,影响下一步计算。
    MOV AX, 0xFFFF  ; AX = 65535
    MOV BX, 1       ; BX = 1
    
    ADD AX, BX      ; AX = 0,CF = 1(低位加法产生进位)
    ADC DX, 0       ; DX = 1,CF = 0(高位加法无进位)
    
5. 多精度加法实战:64 位加法
  • 任务:计算 0x123456789ABCDEF + 0xFEDCBA987654321
  • 步骤
    ; 被加数:0x123456789ABCDEF
    MOV EAX, 0x9ABCDEF  ; 低位(低 32 位)
    MOV EDX, 0x12345678 ; 高位(高 32 位)
    
    ; 加数:0xFEDCBA987654321
    MOV EBX, 0x7654321  ; 低位
    MOV ECX, 0xFEDCBA98 ; 高位
    
    ; 第一步:加低位
    ADD EAX, EBX        ; EAX = 0x9ABCDEF + 0x7654321 = 0x11111110
                        ; CF = 1(产生进位)
    
    ; 第二步:加高位,并带上低位的进位
    ADC EDX, ECX        ; EDX = 0x12345678 + 0xFEDCBA98 + 1 = 0x111111111
                        ; CF = 1(最终结果溢出 64 位,需扩展到 128 位)
    
    ; 最终结果:[EDX:EAX] = 0x1111111111111110
    
6. 标志位与 ADD 完全相同
标志位含义
CF进位标志。无符号数运算溢出时置 1(如 0xFFFF + 1 → CF=1)。
ZF零标志。结果为 0 时置 1(如 0xFFFF + 1 + CF=1 → ZF=1)。
SF符号标志。结果为负数时置 1(有符号数视角)。
OF溢出标志。有符号数运算溢出时置 1(如 0x7FFFFFFF + 1 + CF=1 → OF=1)。
PF奇偶标志。结果的低 8 位中 1 的个数为偶数时置 1。
AF辅助进位标志。低 4 位向高 4 位有进位时置 1。
7. 生活类比:接力赛中的 “传递接力棒”
  • ADD:第一棒选手跑完自己的赛程。
  • ADC:第二棒选手接过第一棒的接力棒(进位 CF),再跑完自己的赛程。
    ; 第一棒:计算低位,并产生进位(接力棒)
    ADD EAX, EBX        ; EAX = 低位和,CF = 进位
    
    ; 第二棒:接过进位(接力棒),计算高位
    ADC EDX, ECX        ; EDX = 高位和 + 进位
    
8. 常见错误清单
  1. 忘记 ADC 依赖 CF

    ADD AX, BX      ; 执行加法,但没保存进位
    MOV CX, 0
    ADC CX, 0       ; 错误!CF 可能不是预期值
    
  2. 多精度加法顺序错误

    ; 错误顺序:先加高位,后加低位
    ADC EDX, ECX    ; 错误!此时 CF 还未被低位加法设置
    ADD EAX, EBX    ; 正确顺序应该是先加低位,再加高位
    
  3. 结果溢出时未扩展位数

    ; 计算 0xFFFFFFFF + 0xFFFFFFFF
    MOV EAX, 0xFFFFFFFF
    MOV EBX, 0xFFFFFFFF
    ADD EAX, EBX    ; EAX = 0xFFFFFFFE,CF = 1
    ADC EDX, 0      ; EDX = 1
    ; 结果:[EDX:EAX] = 0x00000001FFFFFFFE(正确)
    
    ; 若不使用 EDX 存高位,结果会溢出丢失
    
9. 一句话总结

ADC 是处理大数加法的关键:先让 ADD 计算低位并产生进位(CF),再用 ADC 把进位传递到高位计算中,就像接力赛一样!

三,INC(自增指令):计算器里的 “+1” 按钮

1. 功能:让数值自己加 1
  • 公式目标 = 目标 + 1
    比如 INC AX 就是让 AX 里的数加 1,相当于 ADD AX, 1,但更简洁。
2. 能操作哪些数?
  • 寄存器自增
    MOV CX, 10    ; CX = 10
    INC CX        ; CX = 11
    
  • 内存自增
    MOV [COUNT], 5  ; 内存地址 COUNT 存 5
    INC [COUNT]     ; [COUNT] = 6
    
  • 不支持立即数
    INC 5         ; 错误!不能直接对立即数自增
    
3. 与 ADD 的核心区别:不影响进位标志(CF)
  • INC 不改变 CF
    MOV AL, 255   ; AL = 255(0xFF)
    INC AL        ; AL = 0(255+1=256),但 CF 保持不变(仍为 0)
    
  • ADD 会影响 CF
    MOV AL, 255   ; AL = 255
    ADD AL, 1     ; AL = 0,CF = 1(产生进位)
    
4. 标志位影响

INC 只影响 5 个标志位(不影响 CF):

标志位含义
ZF零标志。结果为 0 时置 1(如 0xFF + 1 → ZF=1)。
SF符号标志。结果为负数时置 1(有符号数视角)。
OF溢出标志。有符号数运算溢出时置 1(如 0x7F + 1 → OF=1,即 +127+1)。
PF奇偶标志。结果的低 8 位中 1 的个数为偶数时置 1(如 0x02 → PF=1)。
AF辅助进位标志。低 4 位向高 4 位有进位时置 1(如 0x0F + 1 → AF=1)。
5. 生活类比:电梯楼层按钮
  • INC 指令:相当于电梯的 “上一层” 按钮。
    MOV AX, 5     ; 当前在 5 楼
    INC AX        ; 按“上一层” → 到 6 楼
    
  • 与 ADD 的区别
    • INC 只能固定上一层(+1),不能自定义加多少。
    • ADD 像输入目标楼层,可以加任意数(如 ADD AX, 3 上 3 层)。
6. 常见用途:循环计数器
  • 场景:实现循环 10 次的逻辑。
    MOV CX, 0     ; 计数器初始化为 0
    
7. 常见错误
  1. 误以为 INC 会影响 CF

    MOV AL, 255
    INC AL        ; AL = 0,但 CF 不变(仍为 0)
    JC OVERFLOW   ; 错误!不会跳转到 OVERFLOW,因为 CF=0
    
     
    • 正确做法:若需要检测溢出,应使用 ADD AL, 1 或结合 OF 标志。
  2. 自增内存时忘记指定大小

    INC [NUM]     ; 错误!汇编器不知道是对字节、字还是双字自增
    
    ; 正确做法:明确大小
    INC BYTE PTR [NUM]  ; 对字节自增
    INC WORD PTR [NUM]  ; 对字自增
    
  3. 在多精度加法中误用 INC

    ; 错误:用 INC 处理进位
    ADD AX, BX    ; 低位加法可能产生进位 CF
    INC DX        ; 错误!应使用 ADC DX, 0 来加上 CF
    
    ; 正确流程:
    ADD AX, BX    ; 先加低位
    ADC DX, 0     ; 再加高位并带上进位
    
  4. 循环计数方向错误

    ; 错误:从 0 开始递增到 10(循环 11 次)
    MOV CX, 0
    
8. 一句话总结

INC 是个 “偷懒版” 的 ADD,专门用来加 1,优点是不影响进位标志(CF),适合做计数器,但别用它处理需要进位的大数加法!

四,AAA(非压缩 BCD 加法调整):十进制加法的 “翻译官”

1. 功能:将二进制加法结果调整为非压缩 BCD 码
  • 什么是非压缩 BCD 码?
    每个十进制数字(0-9)用 1 个字节存储,高 4 位为 0,低 4 位为数字的二进制表示。
    例如:十进制 56 表示为 AH=5, AL=6(即 AX=0x0506)。

  • AAA 的作用
    在执行 非压缩 BCD 加法 后,将 AL 中的二进制结果调整为合法的 BCD 码,并处理进位到 AH

2. 调整规则:分两步走
  1. 判断是否需要调整
    • 如果 AL 的低 4 位 > 9 或 辅助进位标志 AF=1,则执行调整。
  2. 执行调整
    • AL = AL + 6(修正低 4 位)。
    • AH = AH + 1(进位到高位)。
    • AF = CF = 1(设置进位标志)。
    • 清除 AL 的高 4 位(确保结果为非压缩 BCD)。
3. 使用场景:十进制加法
  • 典型流程
    ; 计算非压缩 BCD 的 57 + 26 = 83
    MOV AX, 0x0507  ; AH=5(十位), AL=7(个位)→ 表示 BCD 57
    MOV BL, 0x06    ; BL=6(另一个数的个位)
    
    ADD AL, BL      ; AL = 7 + 6 = 13(二进制 0x0D)
                    ; 此时 AL 不是合法的 BCD(低 4 位 D>9)
    
    AAA             ; 调整:
                    ; 1. AL = 0x0D + 6 = 0x13 → 低 4 位为 3
                    ; 2. AH = 5 + 1 = 6
                    ; 3. 清除 AL 高 4 位 → AL = 0x03
                    ; 结果:AX = 0x0603(BCD 63,即 57+6=63)
    
4. 标志位影响

AAA 只影响 2 个标志位:

标志位含义
AF辅助进位标志。调整时置 1(表示低 4 位向高 4 位有进位)。
CF进位标志。调整时置 1(表示向高位有进位)。
其他标志位未定义(ZF、SF、OF、PF 状态不确定,不可依赖)。
5. 生活类比:超市找零的 “十进制修正”
  • 场景:你有 5 张 10 元AH=5)和 7 张 1 元AL=7),收银员找零 6 元BL=6)。
  • 错误计算:直接二进制相加 7+6=13(0x0D),但十进制中不存在 “13 元” 纸币。
  • AAA 的修正
    1. 把 13 元拆成 1 张 10 元 和 3 张 1 元
    2. 把 1 张 10 元加到 5 张 10 元中 → AH=6
    3. 剩下 3 张 1 元 → AL=3
    4. 最终得到 6 张 10 元 + 3 张 1 元(即 BCD 63)。
6. 常见错误清单
  1. 忘记在加法后调用 AAA

    MOV AX, 0x0507
    ADD AL, 6     ; 直接加法,结果 AL=0x0D(非法 BCD)
    ; 错误:未调用 AAA 调整,后续处理会出错
    
  2. 对非 BCD 数使用 AAA

    MOV AL, 0x1F   ; AL=31(非 BCD 数)
    ADD AL, 5     ; AL=36(0x24)
    AAA           ; 错误!AAA 只适用于 BCD 加法
    
  3. 误解标志位状态

    AAA           ; 执行后 AF=1, CF=1
    JZ DONE       ; 错误!ZF 未被定义,跳转条件不可靠
    
7. 一句话总结

AAA 是 BCD 码加法的 “纠错器”,确保二进制加法结果符合十进制规则,自动处理进位并修正低位,就像超市收银员把零钱换成整钱一样自然!

五,DAA(压缩 BCD 加法调整):十进制加法的 “纠错器”

1. 什么是压缩 BCD 码?
  • 用 1 个字节存 2 位十进制数
    高 4 位表示十位,低 4 位表示个位,每 4 位最大值为 1001(即 9)。
    例如:
    • 0101 0110 → 高 4 位 0101=5,低 4 位 0110=6 → 表示十进制 56
    • 1001 1000 → 表示十进制 98
2. 为什么需要 DAA?
  • 直接二进制加法会出错
    例如计算 56 + 37(压缩 BCD 码):
    MOV AL, 56H  ; AL = 0101 0110B(十进制 56)
    ADD AL, 37H  ; AL = 01010110 + 00110111 = 10001101B(8DH,非 BCD 码!)
    

    结果 8DH 不是合法的 BCD 码(低 4 位 1101=13 > 9),需要修正为 93H(56+37=93)。
3. DAA 如何调整?分两步检查修正
  1. 检查低 4 位(个位)
    • 如果 低 4 位 > 9(即 1010~1111)或 AF=1(辅助进位),则:
      • AL += 6(修正低 4 位),并置 AF=1
  2. 检查高 4 位(十位)
    • 如果 高 4 位 > 9 或 CF=1(进位),则:
      • AL += 60H(修正高 4 位),并置 CF=1
4. 详细示例:56 + 37 = 93
; 初始值:56(0101 0110B)和 37(0011 0111B)
MOV AL, 56H     ; AL = 0101 0110B
ADD AL, 37H     ; 二进制加法:
                ;   0101 0110
                ; + 0011 0111
                ; -----------
                ;   1000 1101B(8DH,低 4 位 1101=13 > 9,非法 BCD)

; DAA 调整过程:
DAA             ; 1. 低 4 位 1101 > 9 → AL += 6(0110B):
                ;    1000 1101 + 0000 0110 = 1001 0011B(93H,合法 BCD)
                ; 2. 高 4 位 1001 = 9 ≤ 9 → 无需修正
                ; 最终 AL = 93H(十进制 93),CF=0,AF=1
5. 进位示例:99 + 1 = 100
MOV AL, 99H     ; AL = 1001 1001B(十进制 99)
ADD AL, 01H     ; 二进制加法:
                ;   1001 1001
                ; + 0000 0001
                ; -----------
                ;   1001 1010B(9AH,低 4 位 1010=10 > 9,非法 BCD)

; DAA 调整过程:
DAA             ; 1. 低 4 位 1010 > 9 → AL += 6:
                ;    1001 1010 + 0000 0110 = 1010 0000B(A0H,高 4 位 1010=10 > 9)
                ; 2. 高 4 位 1010 > 9 → AL += 60H:
                ;    1010 0000 + 0110 0000 = 0000 0000B(00H),CF=1
                ; 最终 AL = 00H,CF=1(表示百位进位 1,结果为 100)
6. 生活类比:超市收银机的十进制加法
  • 场景:你买了 99 元 商品,支付 100 元,需计算找零。
  • 计算机内部
    1. 收银机用压缩 BCD 码存储金额(99 → 1001 1001)。
    2. 直接二进制加法 99 + 1 = 9AH,但 9AH 不是合法的 BCD 码(低 4 位 = 10)。
    3. DAA 像收银员手动调整:
      • 发现低 4 位超过 9 → 加 6 修正为 A0H
      • 又发现高 4 位超过 9 → 再加 60H,同时向百位进 1 → 最终结果 00H(找零 0 元,实际支付 100 元)。
7. 常见错误清单
  1. 对非 BCD 码使用 DAA

    MOV AL, 0FH   ; AL = 15(二进制 0000 1111,非 BCD 码)
    ADD AL, 01H   ; AL = 10H(16)
    DAA           ; 错误!DAA 只能用于 BCD 码加法,结果无意义
    
  2. 未先执行加法指令

    MOV AL, 56H   ; 直接加载 BCD 码
    DAA           ; 错误!DAA 必须紧跟在 ADD/ADC 后使用
    
  3. 混淆压缩 BCD 和非压缩 BCD

    • 压缩 BCD:1 字节存 2 位(如 56H 表示 56),用 DAA 调整。
    • 非压缩 BCD:1 字节存 1 位(如 05H 表示 5),用 AAA 调整。
8. 一句话总结

DAA 是压缩 BCD 码加法的 “纠错器”,专门解决二进制加法在十进制下的 “进位溢出” 问题,确保结果符合人类的十进制计算习惯!

六,从 ALU 到应用层:加法指令的三重实战价值

1. 调试排错的显微镜

当你遇到 “程序计算结果与预期不符” 时,第一反应应是:

  • 检查操作数长度是否匹配(如ALBX混加导致截断)
  • DEBUG命令查看CF/OF标志,判断是无符号溢出还是有符号溢出
  • 在多精度运算中,确认ADC是否正确承接了ADD的进位

2. 性能优化的手术刀

  • INCADD reg, 1少一个字节 opcode,在循环计数中可减少指令缓存压力
  • 利用DAA实现十进制运算时,比纯软件转换快 3-5 倍(实测数据)
  • 避免在AAA/DAA前使用影响标志位的指令,防止调整逻辑错乱

3. 体系结构的望远镜 

理解加法指令集,你将看清计算机设计的三大哲学:

  • 正交性:操作数类型(寄存器 / 内存 / 立即数)与操作长度(8/16/32 位)的正交组合
  • 状态机思维:标志位作为指令执行的 “元数据”,串联起条件跳转、循环控制等上层逻辑
  • 向后兼容性:从 8086 到现代 x86-64,ADC指令始终保留着处理跨寄存器进位的原始功能

延伸思考:当 CPU 执行ADD EAX, EBX时,至少涉及哪些硬件单元?(提示:算术逻辑单元、标志寄存器、总线控制器、缓存一致性协议)欢迎在评论区写下你的答案。

下一篇我们将聚焦减法指令家族(SUB/SBB/DEC/NEG),解析 “借位机制” 与 “补码运算” 的底层逻辑。关注我,一起用汇编语言解剖计算机的数字神经系统。

本文技术要点总结

  • 5 类加法指令的操作数规则、标志位影响、典型用例
  • 非压缩 / 压缩 BCD 码的本质区别与调整算法
  • 多精度加法的 “进位接力” 实现模式
  • 指令集设计中的硬件约束与工程权衡

适合读者:计算机组成原理学习者、系统级程序员、逆向工程爱好者
建议实践:用 NASM 编写一段 32 位加法程序,结合objdump反汇编与gdb调试,观察标志位变化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南玖yy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值