asm:常见指令大全

常见指令大全

  • 算数指令
    • INC 指令
    • DEC 指令
    • ADD 指令
    • SUB指令
    • MUL指令
    • IMUL指令
    • DIV指令
    • IDIV指令
  • 逻辑指令
    • AND指令
    • OR指令
    • XOR 指令
    • TEST指令
    • NOT指令
  • 跳转指令
    • 条件跳转指令
    • 无条件跳转指令

算数指令

INC 指令

INC的全称是Increment,表示“增加”、“递增”的意思。
INC 指令用于将操作数加 1。它对可以在寄存器或内存中的单个操作数起作用。

INC 指令的语法如下:

INC destination
目标操作数 可以是 8 位,16 位或 32 位操作数。
实例
INC EBX      ; 32 位寄存器 自增 1
INC DL       ; 8 位寄存器 自增 1
INC [count]  ; 变量 count 自增 1

DEC 指令

DEC的全称是Decrement,表示“减少”、“递减”的意思
DEC 指令用于将操作数减 1。它对可以在寄存器或内存中的单个操作数起作用。

DEC 指令的语法如下:

DEC destination
目标操作数 可以是 8 位,16 位或 32 位操作数。
实例
INC EBX      ; 32 位寄存器 自增 1
INC DL       ; 8 位寄存器 自增 1
INC [count]  ; 变量 count 自增 1

ADD 指令

用于将两个操作数相加并将结果存储到一个目标操作数中。ADD指令的语法和功能如下:

ADD destination, source

其中,destination表示目标操作数,可以是一个寄存器或内存地址;source表示源操作数,可以是一个立即数、寄存器或内存地址。ADD指令将目标操作数和源操作数相加,并将结果存储到目标操作数中。

例如,以下汇编代码使用ADD指令将寄存器AX和BX中的值相加,并将结果存储到AX寄存器中:

MOV AX, 10   ; 将立即数10存储到AX寄存器中
MOV BX, 20   ; 将立即数20存储到BX寄存器中
ADD AX, BX   ; 将AX寄存器和BX寄存器中的值相加,结果存储到AX寄存器中

注意:目标操作数和源操作数不能同时为内存地址

在执行ADD指令时,需要注意以下几点:

  1. 目标操作数和源操作数的数据类型必须相同。例如,如果目标操作数是一个字节(8位),则源操作数也必须是一个字节。
  2. 如果源操作数是一个内存地址,则需要使用方括号将其括起来。例如,ADD AX, [BX]表示将AX寄存器和BX寄存器指向的内存地址中的值相加。
  3. ADD指令可能会产生进位(carry),因此需要根据具体情况进行处理。例如,在进行无符号整数加法时,如果结果超出了目标操作数的范围,则会发生进位。

SUB指令

SUB指令用于将两个操作数相减,并将结果存储到一个目标操作数中。其余与ADD类似。

MUL指令

MUL指令是一种汇编语言中的算术指令,用于将两个操作数相乘,并将结果存储在一个目标操作数中。MUL指令的格式如下:

MUL destination

其中,destination表示目标操作数,可以是一个寄存器、立即数或内存地址。具体描述如下:

  • 如果 destination 是一个寄存器,则 MUL 指令将 AX 寄存器中的值与该寄存器中的值相乘,并将结果存储在 DX:AX 寄存器中。例如,执行 MUL BX 将计算 AX * BX,并将结果存储在 DX:AX 中。
  • 如果 destination 是一个内存地址,则需要使用方括号将其括起来。MUL 指令将 AX 寄存器中的值与该内存地址中的值相乘,并将结果存储在 DX:AX 寄存器中。例如,执行 MUL [BX] 将计算 AX * (数据段中 BX 指向的地址处的值) 并将结果存储在 DX:AX 中。
  • 如果 destination 是一个立即数,则必须是一个无符号整数,并且大小必须与 AX 寄存器的大小匹配。MUL 指令将 AX 寄存器中的值与该立即数相乘,并将结果存储在 DX:AX 寄存器中。例如,执行 MUL 5 将计算 AX * 5 并将结果存储在 DX:AX 中。

需要注意的是,在执行 MUL 指令之前,如果 DX 寄存器中有值,则需要将其清零,以避免出现错误的结果。可以使用 XOR 指令将 DX 寄存器清零,例如 XOR DX, DX

另外,由于 MUL 指令是一种无符号整数乘法指令,因此不能用于执行有符号整数乘法运算,否则会产生错误的结果。

IMUL指令

IMUL是一种汇编指令,用于执行有符号整数乘法运算。它可以将两个操作数相乘,并将结果存储在一个目标操作数中。IMUL指令的语法格式如下:

IMUL destination, source

其中,destination表示目标操作数,可以是一个寄存器、内存地址或立即数;source表示源操作数,可以是一个寄存器、内存地址或立即数。具体来说:

  • 如果 destination 是一个寄存器,则 IMUL 指令将该寄存器中的值与 source 中的值相乘,并将结果存储在 destination 中。例如,执行 IMUL BX, AX 将计算 BX = BX * AX 并将结果存储在 BX 中。
  • 如果 destination 是一个内存地址,则需要使用方括号将其括起来。IMUL 指令将该内存地址中的值与 source 中的值相乘,并将结果存储在该内存地址中。例如,执行 IMUL [BX], 5 将计算 (数据段中 BX 指向的地址处的值) * 5 并将结果存储在该地址中。
  • 如果 destination 是一个立即数,则必须是一个有符号整数,并且大小必须与 source 的大小匹配。IMUL 指令将该立即数与 source 相乘,并将结果存储在 source 中。例如,执行 IMUL AX, -5 将计算 AX = AX * (-5) 并将结果存储在 AX 中。

同MUL指令一样,在执行 IMUL 指令之前,如果 DX 寄存器中有值,则需要使用同样的方法将其清零。

另外,由于 IMUL 指令是一种有符号整数乘法指令,因此可以用于执行有符号整数乘法运算。IMUL 指令会对结果进行符号扩展,以保留正确的符号位。例如,如果执行 IMUL AX, -2,则会将 AX 寄存器中的值乘以 -2,并将结果存储在 AX 中。如果 AX 中的值为 1000(二进制表示),则结果为 1111 1111 1111 0000(二进制表示)。

在执行 IMUL 指令时,还需要注意以下几点:

  1. 目标操作数和源操作数必须是同样大小的有符号整数。
  2. 如果源操作数是一个立即数,则必须是一个有符号整数,并且大小必须与目标操作数匹配。
  3. 如果操作数是一个内存地址,则需要使用方括号将其括起来。例如,IMUL [BX], 5表示将数据段中 BX 指向的地址处的值乘以5。
  4. 在执行IMUL指令之前,必须将高位清零,否则可能会导致错误的结果。可以使用XOR指令将DX寄存器清零:XOR DX, DX

DIV指令

DIV指令是x86汇编语言中的一种算术指令,用于执行无符号整数除法操作。根据被除数和除数的数据类型不同,DIV指令有三种格式:

  1. DIV r/m8指令:将一个16位或32位的无符号整数除以一个8位的无符号整数,并返回商和余数。其语法格式如下:
DIV r/m8

其中,r/m8可以是寄存器或内存地址,指定了除数。被除数需要存储在AX(16位)或DX:AX(32位)寄存器中。

例如,下面的代码演示了使用DIV r/m8指令将16位整数bx除以8位整数al,并将商存储在ax寄存器中,余数存储在dx寄存器中:

MOV AX, BX    ; 将BX复制到AX中
MOV DX, 0     ; 初值化DX为0
MOV AL, 10    ; 将10存储到AL中
DIV AL        ; 将AX除以AL,商存储在AX中,余数存储在DX中
  1. DIV r/m16指令:将一个32位的无符号整数除以一个16位的无符号整数,并返回商和余数。其语法格式如下:
DIV r/m16

其中,r/m16可以是寄存器或内存地址,指定了除数。被除数需要存储在DX:AX寄存器中。

例如,下面的代码演示了使用DIV r/m16指令将32位整数num除以16位整数divisor,并将商存储在ax寄存器中,余数存储在dx寄存器中:

MOV EAX, num      ; 将num复制到EAX中
MOV EDX, 0        ; 初值化EDX为0
MOV BX, divisor   ; 将divisor复制到BX中
DIV BX            ; 将EAX除以BX,商存储在AX中,余数存储在DX中
  1. DIV r/m32指令:将一个64位的无符号整数除以一个32位的无符号整数,并返回商和余数。其语法格式如下:
DIV r/m32

其中,r/m32可以是寄存器或内存地址,指定了除数。被除数需要存储在EDX:EAX寄存器中。

例如,下面的代码演示了使用DIV r/m32指令将64位整数num除以32位整数divisor,并将商存储在eax寄存器中,余数存储在edx寄存器中:

MOV EAX, DWORD PTR [num + 4]   ; 将num的高32位复制到EAX中
MOV EDX, DWORD PTR [num]       ; 将num的低32位复制到EDX中
MOV EBX, divisor               ; 将divisor复制到EBX中
DIV EBX                        ; 将EDX:EAX除以EBX,商存储在EAX中,余数存储在EDX中

需要注意的是,如果除数为0,则会产生“divide by zero”异常。因此,在使用DIV指令进行除法操作时,需要确保除数是非零的。

IDIV指令

与DIV指令操作和原理一致。

逻辑指令

AND指令

AND指令是x86架构中的一种汇编指令,用于执行按位与(bitwise and)操作。其语法格式为:

AND destination, source

其中,destination和source都可以是寄存器或内存地址。执行完毕后,将destination和source进行按位与(bitwise and)操作,并将结果存储到destination中。

下面是一些AND指令的示例:

  1. 按位与两个寄存器

    MOV AX, 0FF00h     ; 将0FF00h存储到AX寄存器中
    AND AX, 0F00h      ; 将AX寄存器中的值与0F00h按位与,并将结果存储回AX寄存器中
    

    这个示例将AX寄存器中的高字节清零,只保留了低字节中的高4位。

  2. 按位与一个寄存器和一个内存地址

    MOV EBX, [ESI]     ; 将ESI地址处存储的值读取到EBX寄存器中
    AND EBX, 0FFh      ; 将EBX寄存器中的值与0FFh按位与,并将结果存储回EBX寄存器中
    

    这个示例将EBX寄存器中的值的高字节清零,只保留了低字节中的8位。

  3. 按位与两个内存地址

    MOV EDI, OFFSET array1   ; 将array1的内存地址存储到EDI寄存器中
    MOV ESI, OFFSET array2   ; 将array2的内存地址存储到ESI寄存器中
    AND DWORD PTR [EDI], DWORD PTR [ESI]  ; 将array1和array2中相同偏移量处的值按位与,并将结果存储回array1中
    

    这个示例将array1数组中相同偏移量处的值与array2数组中相同偏移量处的值进行按位与操作,并将结果存储回array1数组中相同偏移量处的位置。

OR指令

OR指令是x86架构中的一种汇编指令,用于执行按位或(bitwise or)操作。其语法格式为:

OR destination, source

其中,destination和source都可以是寄存器或内存地址。执行完毕后,将destination和source进行按位或(bitwise or)操作,并将结果存储到destination中。

下面是一些OR指令的示例:

  1. 按位或两个寄存器

    MOV AX, 0F0Fh     ; 将0F0Fh存储到AX寄存器中
    OR AX, 00FFh      ; 将AX寄存器中的值与00FFh按位或,并将结果存储回AX寄存器中
    

    这个示例将AX寄存器中的低字节设置为0xFF,而不影响高字节。

  2. 按位或一个寄存器和一个内存地址

    MOV EBX, [ESI]     ; 将ESI地址处存储的值读取到EBX寄存器中
    OR EBX, 0FFh       ; 将EBX寄存器中的值与0FFh按位或,并将结果存储回EBX寄存器中
    

    这个示例将EBX寄存器中的低字节设置为0xFF,而不影响高字节。

  3. 按位或两个内存地址

    MOV EDI, OFFSET array1   ; 将array1的内存地址存储到EDI寄存器中
    MOV ESI, OFFSET array2   ; 将array2的内存地址存储到ESI寄存器中
    OR DWORD PTR [EDI], DWORD PTR [ESI]  ; 将array1和array2中相同偏移量处的值按位或,并将结果存储回array1中
    

    这个示例将array1数组中相同偏移量处的值与array2数组中相同偏移量处的值进行按位或操作,并将结果存储回array1数组中相同偏移量处的位置。

XOR 指令

XOR指令是一种逻辑运算指令,用于对两个操作数进行异或(XOR)运算,并将结果保存到目标操作数中。在大多数计算机体系结构中,XOR指令通常被表示为“XOR”或者“^”,例如在C语言中,XOR运算可以通过“^”符号实现。

XOR运算的规则如下:

  • 如果两个操作数相等,则运算结果为0。
  • 如果两个操作数不相等,则运算结果为1。

以下是几个示例:

  • 0 ^ 0 = 0
  • 0 ^ 1 = 1
  • 1 ^ 0 = 1
  • 1 ^ 1 = 0

在汇编语言中,XOR指令通常使用以下格式表示:

XOR destination, source

其中,destination表示目标操作数,source表示源操作数。XOR指令将destinationsource进行异或运算,并将结果保存到destination中。

例如,在x86汇编语言中,可以使用以下指令将寄存器AX和另一个寄存器BX进行异或运算,并将结果保存到AX中:

XOR AX, BX

在执行这条指令后,AX中的值将等于AX ^ BX

TEST指令

TEST指令是x86架构中的一种汇编指令,用于执行按位与(bitwise and)操作,但不将结果写回到任何寄存器或内存中。其语法格式为:

TEST destination, source

其中,destination和source都可以是寄存器或内存地址。执行完毕后,将destination和source进行按位与操作,并根据结果设置标志寄存器(FLAGS寄存器)的数值。

TEST指令并不会修改destination或source寄存器或内存地址中存储的值,而是通过按位与操作的结果来设置标志寄存器的数值,以便后续指令能够根据标志寄存器中的状态进行分支判断等操作。

下面是一些TEST指令的示例:

  1. 按位与两个寄存器并测试结果

    MOV AX, 0FF00h     ; 将0FF00h存储到AX寄存器中
    TEST AX, 0F0Fh     ; 将AX寄存器中的值与0F0Fh按位与,并根据结果设置标志寄存器的数值
    

    这个示例将AX寄存器中的高字节清零,只保留了低字节中的高4位,并测试了这四位是否为非零值。

  2. 按位与一个寄存器和一个内存地址并测试结果

    MOV EBX, [ESI]     ; 将ESI地址处存储的值读取到EBX寄存器中
    TEST EBX, 0FFh     ; 将EBX寄存器中的值与0FFh按位与,并根据结果设置标志寄存器的数值
    

    这个示例将EBX寄存器中的高字节清零,只保留了低字节中的8位,并测试了这8位是否为非零值。

  3. 按位与两个内存地址并测试结果

    MOV EDI, OFFSET array1   ; 将array1的内存地址存储到EDI寄存器中
    MOV ESI, OFFSET array2   ; 将array2的内存地址存储到ESI寄存器中
    TEST DWORD PTR [EDI], DWORD PTR [ESI]  ; 将array1和array2中相同偏移量处的值按位与,并根据结果设置标志寄存器的数值
    

    这个示例将array1数组中相同偏移量处的值与array2数组中相同偏移量处的值进行按位与操作,并测试操作结果是否为非零值。

NOT指令

NOT指令是x86架构中的一种汇编指令,用于执行按位取反(bitwise not)操作。其语法格式为:

NOT destination

其中,destination可以是寄存器或内存地址。执行完毕后,将destination进行按位取反(bitwise not)操作,并将结果存储回destination中。

下面是一些NOT指令的示例:

  1. 对一个寄存器进行按位取反

    MOV AX, 0FF00h     ; 将0FF00h存储到AX寄存器中
    NOT AX             ; 对AX寄存器中的值进行按位取反,并将结果存储回AX寄存器中
    

    这个示例将AX寄存器中的低字节设置为0x00,高字节设置为0x0F。

  2. 对一个内存地址进行按位取反

    MOV ESI, OFFSET array   ; 将array的内存地址存储到ESI寄存器中
    NOT DWORD PTR [ESI]     ; 对array数组中第一个元素的值进行按位取反,并将结果存储回该元素中
    

    这个示例将array数组中第一个元素的每一位进行取反操作。

  3. 对两个内存地址进行按位取反并测试结果

    MOV EDI, OFFSET array1   ; 将array1的内存地址存储到EDI寄存器中
    MOV ESI, OFFSET array2   ; 将array2的内存地址存储到ESI寄存器中
    NOT DWORD PTR [EDI]      ; 对array1数组中第一个元素的值进行按位取反,并将结果存储回该元素中
    TEST DWORD PTR [EDI], DWORD PTR [ESI]   ; 测试array1数组中第一个元素的值是否与array2数组中相同偏移量处的值按位与后等于0
    

    这个示例将array1数组中第一个元素的每一位进行取反操作,然后测试操作结果是否与array2数组中相同偏移量处的值按位与后等于0,即测试这两个数组在此位置上是否具有相反的位模式。

跳转指令

条件跳转指令

条件跳转指令是x86汇编中的一类指令,用于根据标志寄存器(FLAGS寄存器)的数值进行分支判断,根据条件的成立与否来跳转到不同的代码块中执行。根据判断条件的不同,x86汇编提供了多种条件跳转指令。

常见的条件跳转指令及其含义如下:

  • JE(Jump if Equal):如果上一个比较操作的结果为相等,则跳转。
  • JNE(Jump if Not Equal):如果上一个比较操作的结果为不相等,则跳转。
  • JL(Jump if Less):如果上一个比较操作的结果为小于,则跳转。
  • JLE(Jump if Less or Equal):如果上一个比较操作的结果为小于或等于,则跳转。
  • JG(Jump if Greater):如果上一个比较操作的结果为大于,则跳转。
  • JGE(Jump if Greater or Equal):如果上一个比较操作的结果为大于或等于,则跳转。
  • JA(Jump if Above):如果上一个比较操作的结果为无符号数大于,则跳转。
  • JAE(Jump if Above or Equal):如果上一个比较操作的结果为无符号数大于或等于,则跳转。
  • JB(Jump if Below):如果上一个比较操作的结果为无符号数小于,则跳转。
  • JBE(Jump if Below or Equal):如果上一个比较操作的结果为无符号数小于或等于,则跳转。

这些条件跳转指令通常搭配其他指令使用,例如CMP(Compare)指令用于比较两个操作数,并根据比较结果设置标志寄存器的数值。然后条件跳转指令可以根据标志寄存器中的状态进行分支判断,决定是否跳转到指定的代码块中执行。

下面是一个简单的示例程序,演示了如何使用条件跳转指令:

MOV AX, 10    ; 将10存储到AX寄存器中
MOV BX, 20    ; 将20存储到BX寄存器中
CMP AX, BX    ; 比较AX和BX的值,设置标志寄存器的数值
JL less       ; 如果AX < BX,则跳转到less标签处
JMP done      ; 否则跳转到done标签处

less:         ; less标签处的指令
MOV CX, 30    ; 将30存储到CX寄存器中
JMP done      ; 跳转到done标签处

done:         ; done标签处的指令
...           ; 继续执行后续指令

在这个示例中,首先将10和20存储到AX和BX寄存器中,然后使用CMP指令比较它们的值,并设置标志寄存器的数值。接着使用JL指令进行分支判断,如果AX < BX,则跳转到less标签处执行MOV指令,否则直接跳转到done标签处。最后在done标签处继续执行后续的指令。

无条件跳转指令

JMP指令是x86汇编中的一种无条件跳转指令,用于直接跳转到程序中的另一个位置执行指令。其语法格式为:

JMP destination

其中,destination可以是任何有效的内存地址或标号(label)。执行完这条指令后,CPU会立即跳转到destination指向的内存地址处执行指令。

下面是一些JMP指令的示例:

  1. 跳转到一个标号处

    START:      ; 定义START标号处的指令
    ...
    JMP START   ; 跳转到START标号处继续执行后续指令
    ...
    

    在这个示例中,定义了一个名为START的标号,表示程序中的某个位置。然后使用JMP指令跳转到START标号处继续执行后续指令。

  2. 跳转到一个内存地址处

    MOV EAX, offset myCode   ; 将myCode的内存地址存储到EAX寄存器中
    JMP EAX                  ; 跳转到myCode所在的内存地址处执行指令
    

    在这个示例中,使用MOV指令将myCode的内存地址存储到EAX寄存器中,然后使用JMP指令直接跳转到myCode所在的内存地址处执行指令。

  3. 使用相对偏移量进行跳转

    MOV EBX, offset labelB  ; 将labelB的内存地址存储到EBX寄存器中
    MOV EAX, offset labelA  ; 将labelA的内存地址存储到EAX寄存器中
    SUB EBX, EAX             ; 计算labelB与labelA之间的相对偏移量
    JMP EBX                  ; 跳转到labelB处执行指令
    ...
    labelA:                  ; 标记labelA处的指令
    ...
    labelB:                  ; 标记labelB处的指令
    ...
    

    在这个示例中,首先使用MOV指令将labelA和labelB的内存地址存储到EAX和EBX寄存器中,然后使用SUB指令计算出labelB与labelA之间的相对偏移量,并将其存储回EBX寄存器中。最后使用JMP指令直接跳转到labelB处执行指令。注意,在这个示例中,需要定义labelA和labelB两个标号,以便计算相对偏移量。

你可能感兴趣的:(asm,汇编,指令集)