汇编 - 逻辑指令


处理器指令集提供AND、OR、XOR、TEST和NOT布尔逻辑指令,根据程序的需要测试、设置和清除位。

这些说明的格式 -

先生。 操作说明 格式
1 AND 操作数 1, 操作数 2
2 或者 OR 操作数 1, 操作数 2
3 异或 异或操作数 1、操作数 2
4 测试 TEST 操作数 1、操作数 2
5 不是 非操作数1

所有情况下的第一个操作数可以位于寄存器或内存中。第二个操作数可以位于寄存器/内存中或立即(常量)值。然而,内存到内存的操作是不可能的。这些指令比较或匹配操作数的位并设置 CF、OF、PF、SF 和 ZF 标志。

AND 指令

AND指令用于通过执行按位AND运算来支持逻辑表达式。如果两个操作数的匹配位均为 1,则按位 AND 运算返回 1,否则返回 0。例如 -

             Operand1: 	0101
             Operand2: 	0011
----------------------------
After AND -> Operand1:	0001

AND 运算可用于清除一位或多位。例如,假设BL寄存器包含0011 1010。如果需要将高位清零,则与0FH进行AND运算。

AND	BL,   0FH   ; This sets BL to 0000 1010

我们再举一个例子。如果您想检查给定的数字是奇数还是偶数,一个简单的测试就是检查该数字的最低有效位。如果为 1,则该数字为奇数,否则该数字为偶数。

假设数字在 AL 寄存器中,我们可以写 -

AND	AL, 01H     ; ANDing with 0000 0001
JZ    EVEN_NUMBER

以下程序说明了这一点 -

例子

section .text
   global _start            ;must be declared for using gcc
	
_start:                     ;tell linker entry point
   mov   ax,   8h           ;getting 8 in the ax 
   and   ax, 1              ;and ax with 1
   jz    evnn
   mov   eax, 4             ;system call number (sys_write)
   mov   ebx, 1             ;file descriptor (stdout)
   mov   ecx, odd_msg       ;message to write
   mov   edx, len2          ;length of message
   int   0x80               ;call kernel
   jmp   outprog

evnn:   
  
   mov   ah,  09h
   mov   eax, 4             ;system call number (sys_write)
   mov   ebx, 1             ;file descriptor (stdout)
   mov   ecx, even_msg      ;message to write
   mov   edx, len1          ;length of message
   int   0x80               ;call kernel

outprog:

   mov   eax,1              ;system call number (sys_exit)
   int   0x80               ;call kernel

section   .data
even_msg  db  'Even Number!' ;message showing even number
len1  equ  $ - even_msg 
   
odd_msg db  'Odd Number!'    ;message showing odd number
len2  equ  $ - odd_msg

当上面的代码被编译并执行时,它会产生以下结果 -

Even Number!

用奇数位更改 ax 寄存器中的值,例如 -

mov  ax, 9h                  ; getting 9 in the ax

程序会显示:

Odd Number!

类似地,要清除整个寄存器,您可以将其与 00H 进行“与”操作。

或指令

OR指令用于通过执行按位或运算来支持逻辑表达式。如果任一操作数或两个操作数的匹配位均为 1,则按位 OR 运算符返回 1。如果两个位都为零,则返回 0。

例如,

             Operand1:     0101
             Operand2:     0011
----------------------------
After OR -> Operand1:    0111

OR 运算可用于设置一位或多位。例如,假设AL寄存器包含0011 1010,则需要设置低四位,可以将其与值0000 1111(即FH)进行或运算。

OR BL, 0FH                   ; This sets BL to  0011 1111

例子

以下示例演示了 OR 指令。让我们将值 5 和 3 分别存储在 AL 和 BL 寄存器中,然后指令,

OR AL, BL

应将 7 存储在 AL 寄存器中 -

section .text
   global _start            ;must be declared for using gcc
	
_start:                     ;tell linker entry point
   mov    al, 5             ;getting 5 in the al
   mov    bl, 3             ;getting 3 in the bl
   or     al, bl            ;or al and bl registers, result should be 7
   add    al, byte '0'      ;converting decimal to ascii
	
   mov    [result],  al
   mov    eax, 4
   mov    ebx, 1
   mov    ecx, result
   mov    edx, 1 
   int    0x80
    
outprog:
   mov    eax,1             ;system call number (sys_exit)
   int    0x80              ;call kernel
	
section    .bss
result resb 1

当上面的代码被编译并执行时,它会产生以下结果 -

7

异或指令

XOR指令实现按位异或运算。当且仅当操作数中的位不同时,XOR 运算将结果位设置为 1。如果操作数的位相同(均为 0 或均为 1),则结果位清除为 0。

例如,

             Operand1:     0101
             Operand2:     0011
----------------------------
After XOR -> Operand1:    0110

操作数与其自身进行异或会将操作数更改为0。这用于清除寄存器。

XOR     EAX, EAX

测试指令

TEST 指令的工作原理与 AND 运算相同,但与 AND 指令不同的是,它不会更改第一个操作数。因此,如果我们需要检查寄存器中的数字是偶数还是奇数,我们也可以使用 TEST 指令来完成此操作,而无需更改原始数字。

TEST    AL, 01H
JZ      EVEN_NUMBER

NOT 指令

NOT 指令实现按位 NOT 运算。NOT 运算反转操作数中的位。操作数可以在寄存器中,也可以在存储器中。

例如,

             Operand1:    0101 0011
After NOT -> Operand1:    1010 1100