windows汇编:汇编基础(二)

321 阅读10分钟

前言

在汇编语言中,db(define byte)被称为伪指令,因为它并不是实际的汇编指令,而是一个用于定义数据的指令,用于告诉汇编器如何处理源代码的指令,但它们不直接对应于机器代码的指令。伪指令用于数据定义、内存分配、段定义等目的。

使用伪指令进行数据定义

在汇编中,只有数据内存占用大小.没有数据类型概念.但是在定义的时候,还是会有一些区别.定义大小的如下:

  • db(Define byte) 1字节 8位(8bit)
  • dw(Define Word) 2字节 16位(16bit)
  • dd(Define Double Word) 4字节 32位(32bit)
  • dq(Define Quad Word) 8字节 64位(64bit)

不同数据类型的定义

第一个表示的变量(常量)名称,第二个表示的数据大小,第三个表示的是.

字节(Byte)
var1 db 10           ; 定义一个字节,值为 10
var2 db 'A'         ; 定义一个字符
字(Word)
var1 dw 1000         ; 定义一个字,值为 1000
双字(Double Word)
var1 dd 1234567890  ; 定义一个双字,值为 1234567890
四字(Quad Word)
var1 dq 9876543210123456789 ; 定义一个四字,值为 9876543210123456789
定义单精度浮点数(float)
floatValue real4 3.14      ; 定义一个单精度浮点数
; 或者使用 dd
floatValue dd 3.14
定义双精度浮点数(double)
doubleValue real8 3.141592653589793 ; 定义一个双精度浮点数
; 或者使用 dq
doubleValue dq 3.141592653589793
定义数组(字节数组),其他数组修改数据大小即可
.data
var1 db 10, 20, 30, 40, 50  ; 定义一个字节数组
定义字符串
var1 db 'hello world', 0  ; 定义一个以零结尾的字符串

位操作

按位与(& and

规则:对应二进制位都为1时结果为1,否则为0。 示例 cpp 1 & 1 = 1 // 0b1 & 0b1 = 0b1 1 & 0 = 0 // 0b1 & 0b0 = 0b0 0 & 0 = 0 // 0b0 & 0b0 = 0b0 应用:判断奇偶性、提取特定位

2. 按位或(| or)

规则:对应二进制位只要有一个为1,结果为1。 示例

```
cpp
1 | 0 = 1  // 0b1 | 0b0 = 0b1
0 | 0 = 0  // 0b0 | 0b0 = 0b0
```

应用:设置特定位、快速合并标志

3. 按位异或(^ xor

规则:对应二进制位不同时结果为1,相同时为0。 示例

```
cpp
1 ^ 0 = 1  // 0b1 ^ 0b0 = 0b1
0 ^ 0 = 0  // 0b0 ^ 0b0 = 0b0
```

应用:切换特定位、两数无临时变量交换

  • 任何数与自身异或结果为0(a ⊕ a = 0),且两次异或同一数可恢复原值(a ⊕ b ⊕ b = a)
  • 无需额外变量即可交换两个数
  • ^ b = b ^ a
  • (a ^ b) ^ c = a ^ (b ^ c)
  • ^ b = b
  • ^ a = 0
4. 按位取反(~ not

规则:将操作数的每一位取反(0变1,1变0)。 示例 cpp ~1 = -2 // 0b1 → 0b111111111111111111111111111110(补码表示) 应用:求反码、位掩码操作

5. 左移(<< shl

规则:将二进制位向左移动指定位数,右侧补0。 示例

```
cpp
1 << 1 = 2  // 0b1 → 0b10(十进制2)
```

应用:快速乘法(如 n << 1 等价于 n * 2

6. 右移(>> shr

规则:将二进制位向右移动指定位数,左侧补符号位(算术右移)或0(逻辑右移)。 示例

```
cpp
2 >> 1 = 1  // 0b10 → 0b1(十进制1)
```

应用:快速除法(如 n >> 1 等价于 n / 2

JCC与EFLAG

EFLAG/FFLAG/RFLAG这个寄存器中的值: 主要标志位:

  • 零标志 (ZF):如果运算结果为零,则设置此标志。
  • 符号标志 (SF):如果运算结果为负数,则设置此标志。
  • 进位标志 (CF):在无符号运算中,如果发生进位,则设置此标志。
  • 溢出标志 (OF):如果有符号运算发生溢出,则设置此标志。
  • 辅助进位标志 (AF):用于二进制加法中的低四位进位。

其他标志位:

  • 方向标志 (DF):影响字符串操作的方向。
  • 中断标志 (IF):控制中断的开启和关闭。
  • 陷阱标志 (TF):用于单步调试。
  • 系统标志 (SF):与特权级和系统调用相关。

修改 EFLAGS 的指令

  1. CMP destination, source

    • 功能:比较两个操作数。
    • 标志位影响:
      • ZF:如果 destination 等于 source,则设置为 1;否则为 0。
      • SF:根据 destination - source 的符号更新。
      • OF:根据有符号比较的结果更新。
      • CF:如果 destination < source,则设置为 1。
  2. CMPSB (或 CMPSW, CMPSD, CMPSQ)

    • 功能:比较 ESIEDI 指向的字节(或字、双字、四字)。
    • 标志位影响:
      • ZF:如果指向的字节或字相等,设置为 1;否则为 0。
      • SF:根据比较结果更新。
      • OFCF:根据无符号比较的结果更新。
  3. ADD destination, source

    • 功能:将 source 添加到 destination
    • 标志位影响:
      • ZF:如果相加结果为 0,设置为 1;否则为 0。
      • SF:根据结果的符号更新。
      • OF:如果发生溢出,则设置为 1。
      • CF:如果发生进位,则设置为 1。
  4. SUB destination, source

    • 功能:从 destination 中减去 source
    • 标志位影响:
      • ZF:如果结果为 0,设置为 1;否则为 0。
      • SFOFCF:与 CMP 指令相同,更新相应标志。
  5. INC destination

    • 功能:将 destination 增加 1。
    • 标志位影响:
      • ZF:如果结果为 0,设置为 1;否则为 0。
      • SF:根据结果的符号更新。
      • OF:如果 destination 为最小值,设置为 1;否则为 0。
      • CF:始终为 0。
  6. DEC destination

    • 功能:将 destination 减去 1。
    • 标志位影响:
      • ZF:如果结果为 0,设置为 1;否则为 0。
      • SF:根据结果的符号更新。
      • OF:如果 destination 为最大值,设置为 1;否则为 0。
      • CF:始终为 0。
  7. AND destination, source

    • 功能:对 destinationsource 进行按位与运算。
    • 标志位影响:
      • ZF:如果结果为 0,设置为 1;否则为 0。
      • SF:根据结果的符号更新。
      • PF:根据结果的奇偶性更新。
  8. OR destination, source

    • 功能:对 destinationsource 进行按位或运算。
    • 标志位影响:
      • ZF:如果结果为 0,设置为 1;否则为 0。
      • SF:根据结果的符号更新。
      • PF:根据结果的奇偶性更新。
  9. XOR destination, source

    • 功能:对 destinationsource 进行按位异或运算。
    • 标志位影响:
      • ZF:如果结果为 0,设置为 1;否则为 0。
      • SF:根据结果的符号更新。
      • PF:根据结果的奇偶性更新
  10. MUL / IMUL

    • 功能:MUL 进行无符号乘法,IMUL 进行有符号乘法。两者都将 AX(或 EAX)与操作数相乘,结果放入 DX:AX(或 EDX:EAX)。
    • 标志位影响:
      • CF:如果结果溢出,则设置为 1。
      • OF:如果结果溢出,则设置为 1。
      • ZFSFPF:根据 AX(或 EAX)的结果更新。
  11. DIV / IDIV

    • 功能:DIV 进行无符号除法,IDIV 进行有符号除法。两者用 DX:AX(或 EDX:EAX)作为被除数,除以操作数,结果放入 AL(或 EAX),余数放入 AH(或 EDX)。
    • 标志位影响:
      • CF:如果除法结果溢出,则设置为 1。
      • ZF:如果余数为 0,设置为 1。
      • SF:根据 AL(或 EAX)的结果更新。
      • OF:不受此指令影响。
  12. NEG destination

    • 功能:取 destination 的相反数(即 destination = -destination)。
    • 标志位影响:
      • ZF:如果结果为 0,设置为 1;否则为 0。
      • SF:根据结果的符号更新。
      • OF:如果 destination 为最小值,设置为 1;否则为 0。
      • CF:始终为 0。

JCC指令

条件跳转指令用于根据 EFLAGS 寄存器中的标志决定是否跳转到特定的标签。不同的条件对应不同的跳转指令。

1. 进位标志位(CF - Carry Flag)

含义:用于反映无符号数运算结果是否产生进位或借位。当进行加法运算时,若最高位产生进位;或进行减法运算时,最高位产生借位,则 CF 置为 1,否则置为 0。

对应的跳转指令

-   `jc`(Jump if Carry):若 CF = 1 则跳转。
-   `jnc`(Jump if No Carry):若 CF = 0 则跳转。

2. 零标志位(ZF - Zero Flag)

含义:反映运算结果是否为 0。若运算结果为 0,则 ZF 置为 1;否则置为 0。

对应的跳转指令 - jz(Jump if Zero):若 ZF = 1 则跳转。 - jnz(Jump if Not Zero):若 ZF = 0 则跳转。

3. 符号标志位(SF - Sign Flag)

含义:反映有符号数运算结果的符号。若运算结果为负数(最高位为 1),则 SF 置为 1;若结果为正数或 0(最高位为 0),则 SF 置为 0。

对应的跳转指令 - js(Jump if Sign):若 SF = 1 则跳转。 - jns(Jump if Not Sign):若 SF = 0 则跳转。

4. 溢出标志位(OF - Overflow Flag)

含义:用于反映有符号数运算结果是否溢出。当有符号数运算结果超出了所能表示的范围时,OF 置为 1;否则置为 0。

对应的跳转指令 - jo(Jump if Overflow):若 OF = 1 则跳转。 - jno(Jump if No Overflow):若 OF = 0 则跳转。

5. 奇偶标志位(PF - Parity Flag)

含义:反映运算结果低 8 位中 1 的个数的奇偶性。若低 8 位中 1 的个数为偶数,则 PF 置为 1;若为奇数,则 PF 置为 0。

对应的跳转指令 - jp(Jump if Parity):若 PF = 1 则跳转。 - jnp(Jump if No Parity):若 PF = 0 则跳转。

方向标志位(DF - Direction Flag)

含义:用于控制串操作指令(如 movscmps 等)中地址指针的增减方向。当 DF = 0 时,地址指针自动递增;当 DF = 1 时,地址指针自动递减。

对应的跳转指令:通常没有直接基于 DF 标志位的跳转指令,但可以使用 std(Set Direction Flag,将 DF 置为 1)和 cld(Clear Direction Flag,将 DF 置为 0)指令来设置 DF 的值。

中断允许标志位(IF - Interrupt Enable Flag)

含义:用于控制外部可屏蔽中断的响应。当 IF = 1 时,CPU 可以响应外部可屏蔽中断;当 IF = 0 时,CPU 不响应外部可屏蔽中断。

对应的跳转指令:通常没有直接基于 IF 标志位的跳转指令,但可以使用 sti(Set Interrupt Flag,将 IF 置为 1)和 cli(Clear Interrupt Flag,将 IF 置为 0)指令来设置 IF 的值。

其他跳转指令

  1. je (Jump if Equal)

    • 当 ZF = 1 时跳转。
    • 示例:
      cmp eax, ebx
      je equal_label  ; 如果相等则跳转
      
  2. jne (Jump if Not Equal)

    • 当 ZF = 0 时跳转。
    • 示例:
      cmp eax, ebx
      jne not_equal_label  ; 如果不相等则跳转
      
  3. jg (Jump if Greater)

    • 当 ZF = 0 且 SF = OF 时跳转。
    • 示例:
      cmp eax, ebx
      jg greater_label  ; 如果大于则跳转
      
  4. jl (Jump if Less)

    • 当 SF ≠ OF 时跳转。
    • 示例:
      cmp eax, ebx
      jl less_label  ; 如果小于则跳转
      
  5. jge (Jump if Greater or Equal)

    • 当 ZF = 0 或 SF = OF 时跳转。
    • 示例:
      cmp eax, ebx
      jge greater_equal_label  ; 如果大于或等于则跳转
      
  6. jle (Jump if Less or Equal)

    • 当 SF ≠ OF 或 ZF = 1 时跳转。
    • 例:
      cmp eax, ebx
      jle less_equal_label  ; 如果小于或等于则跳转