📜  汇编-算术指令

📅  最后修改于: 2020-11-05 05:06:20             🧑  作者: Mango


INC指令

INC指令用于将操作数加1。它对可以在寄存器或内存中的单个操作数起作用。

句法

INC指令具有以下语法-

INC destination

操作数目的地可以是8位,16位或32位操作数。

INC EBX         ; Increments 32-bit register
INC DL       ; Increments 8-bit register
INC [count]  ; Increments the count variable

DEC指令

DEC指令用于将操作数减1。它对可以在寄存器或内存中的单个操作数起作用。

句法

DEC指令具有以下语法-

DEC destination

操作数目的地可以是8位,16位或32位操作数。

segment .data
   count dw  0
   value db  15
    
segment .text
   inc [count]
   dec [value]
    
   mov ebx, count
   inc word [ebx]
    
   mov esi, value
   dec byte [esi]

ADD和SUB指令

ADD和SUB指令用于对字节,字和双字大小的二进制数据进行简单的加/减,即分别用于添加或减去8位,16位或32位操作数。

句法

ADD和SUB指令具有以下语法-

ADD/SUB    destination, source

ADD / SUB指令可以发生在-

  • 注册注册
  • 内存注册
  • 注册到内存
  • 注册到常量数据
  • 存储恒定数据

但是,像其他指令一样,使用ADD / SUB指令也无法进行存储器到存储器的操作。 ADD或SUB操作设置或清除溢出和进位标志。

下面的示例将要求用户输入两位数字,分别将这些数字存储在EAX和EBX寄存器中,将这些值相加,将结果存储在“ res ”存储位置中,最后显示结果。

SYS_EXIT  equ 1
SYS_READ  equ 3
SYS_WRITE equ 4
STDIN     equ 0
STDOUT    equ 1

segment .data 

   msg1 db "Enter a digit ", 0xA,0xD 
   len1 equ $- msg1 

   msg2 db "Please enter a second digit", 0xA,0xD 
   len2 equ $- msg2 

   msg3 db "The sum is: "
   len3 equ $- msg3

segment .bss

   num1 resb 2 
   num2 resb 2 
   res resb 1    

section    .text
   global _start    ;must be declared for using gcc
    
_start:             ;tell linker entry point
   mov eax, SYS_WRITE         
   mov ebx, STDOUT         
   mov ecx, msg1         
   mov edx, len1 
   int 0x80                

   mov eax, SYS_READ 
   mov ebx, STDIN  
   mov ecx, num1 
   mov edx, 2
   int 0x80            

   mov eax, SYS_WRITE        
   mov ebx, STDOUT         
   mov ecx, msg2          
   mov edx, len2         
   int 0x80

   mov eax, SYS_READ  
   mov ebx, STDIN  
   mov ecx, num2 
   mov edx, 2
   int 0x80        

   mov eax, SYS_WRITE         
   mov ebx, STDOUT         
   mov ecx, msg3          
   mov edx, len3         
   int 0x80

   ; moving the first number to eax register and second number to ebx
   ; and subtracting ascii '0' to convert it into a decimal number
    
   mov eax, [num1]
   sub eax, '0'
    
   mov ebx, [num2]
   sub ebx, '0'

   ; add eax and ebx
   add eax, ebx
   ; add '0' to to convert the sum from decimal to ASCII
   add eax, '0'

   ; storing the sum in memory location res
   mov [res], eax

   ; print the sum 
   mov eax, SYS_WRITE        
   mov ebx, STDOUT
   mov ecx, res         
   mov edx, 1        
   int 0x80

exit:    
   
   mov eax, SYS_EXIT   
   xor ebx, ebx 
   int 0x80

编译并执行上述代码后,将产生以下结果-

Enter a digit:
3
Please enter a second digit:
4
The sum is:
7

具有硬编码变量的程序-

section    .text
   global _start    ;must be declared for using gcc
    
_start:             ;tell linker entry point
   mov    eax,'3'
   sub     eax, '0'
    
   mov     ebx, '4'
   sub     ebx, '0'
   add     eax, ebx
   add    eax, '0'
    
   mov     [sum], eax
   mov    ecx,msg    
   mov    edx, len
   mov    ebx,1    ;file descriptor (stdout)
   mov    eax,4    ;system call number (sys_write)
   int    0x80    ;call kernel
    
   mov    ecx,sum
   mov    edx, 1
   mov    ebx,1    ;file descriptor (stdout)
   mov    eax,4    ;system call number (sys_write)
   int    0x80    ;call kernel
    
   mov    eax,1    ;system call number (sys_exit)
   int    0x80    ;call kernel
    
section .data
   msg db "The sum is:", 0xA,0xD 
   len equ $ - msg   
   segment .bss
   sum resb 1

编译并执行上述代码后,将产生以下结果-

The sum is:
7

MUL / IMUL指令

有两条指令用于将二进制数据相乘。 MUL(乘法)指令处理未签名的数据,而IMUL(整数乘法)则处理签名的数据。两条指令都影响进位和溢出标志。

句法

MUL / IMUL指令的语法如下-

MUL/IMUL multiplier

在两种情况下,被乘数将在一个累加器中,具体取决于被乘数和乘数的大小,并且根据操作数的大小,生成的乘积还将存储在两个寄存器中。以下部分说明了三种不同情况下的MUL指令-

Sr.No. Scenarios
1

When two bytes are multiplied −

The multiplicand is in the AL register, and the multiplier is a byte in the memory or in another register. The product is in AX. High-order 8 bits of the product is stored in AH and the low-order 8 bits are stored in AL.

Arithmetic1

2

When two one-word values are multiplied −

The multiplicand should be in the AX register, and the multiplier is a word in memory or another register. For example, for an instruction like MUL DX, you must store the multiplier in DX and the multiplicand in AX.

The resultant product is a doubleword, which will need two registers. The high-order (leftmost) portion gets stored in DX and the lower-order (rightmost) portion gets stored in AX.

Arithmetic2

3

When two doubleword values are multiplied −

When two doubleword values are multiplied, the multiplicand should be in EAX and the multiplier is a doubleword value stored in memory or in another register. The product generated is stored in the EDX:EAX registers, i.e., the high order 32 bits gets stored in the EDX register and the low order 32-bits are stored in the EAX register.

Arithmetic3

MOV AL, 10
MOV DL, 25
MUL DL
...
MOV DL, 0FFH    ; DL= -1
MOV AL, 0BEH    ; AL = -66
IMUL DL

以下示例将3乘以2,并显示结果-

section    .text
   global _start    ;must be declared for using gcc
    
_start:             ;tell linker entry point

   mov    al,'3'
   sub     al, '0'
    
   mov     bl, '2'
   sub     bl, '0'
   mul     bl
   add    al, '0'
    
   mov     [res], al
   mov    ecx,msg    
   mov    edx, len
   mov    ebx,1    ;file descriptor (stdout)
   mov    eax,4    ;system call number (sys_write)
   int    0x80    ;call kernel
    
   mov    ecx,res
   mov    edx, 1
   mov    ebx,1    ;file descriptor (stdout)
   mov    eax,4    ;system call number (sys_write)
   int    0x80    ;call kernel
    
   mov    eax,1    ;system call number (sys_exit)
   int    0x80    ;call kernel

section .data
msg db "The result is:", 0xA,0xD 
len equ $- msg   
segment .bss
res resb 1

编译并执行上述代码后,将产生以下结果-

The result is:
6

DIV / IDIV指令

除法运算生成两个元素-余数。如果是乘法,则不会发生溢出,因为使用了双倍长度寄存器来保存乘积。但是,在分割的情况下,可能会发生溢出。如果发生溢出,处理器将产生中断。

DIV(除法)指令用于未签名的数据,而IDIV(整数除法)用于签名的数据。

句法

DIV / IDIV指令的格式-

DIV/IDIV    divisor

股息在累加器中。两条指令都可以使用8位,16位或32位操作数。该操作影响所有六个状态标志。以下部分说明了三种操作数大小不同的除法情况-

Sr.No. Scenarios
1

When the divisor is 1 byte −

The dividend is assumed to be in the AX register (16 bits). After division, the quotient goes to the AL register and the remainder goes to the AH register.

Arithmetic4

2

When the divisor is 1 word −

The dividend is assumed to be 32 bits long and in the DX:AX registers. The high-order 16 bits are in DX and the low-order 16 bits are in AX. After division, the 16-bit quotient goes to the AX register and the 16-bit remainder goes to the DX register.

Arithmetic5

3

When the divisor is doubleword −

The dividend is assumed to be 64 bits long and in the EDX:EAX registers. The high-order 32 bits are in EDX and the low-order 32 bits are in EAX. After division, the 32-bit quotient goes to the EAX register and the 32-bit remainder goes to the EDX register.

Arithmetic6

以下示例将8除以2。被除数8存储在16位AX寄存器中除数2存储在8位BL寄存器中

section    .text
   global _start    ;must be declared for using gcc
    
_start:             ;tell linker entry point
   mov    ax,'8'
   sub     ax, '0'
    
   mov     bl, '2'
   sub     bl, '0'
   div     bl
   add    ax, '0'
    
   mov     [res], ax
   mov    ecx,msg    
   mov    edx, len
   mov    ebx,1    ;file descriptor (stdout)
   mov    eax,4    ;system call number (sys_write)
   int    0x80    ;call kernel
    
   mov    ecx,res
   mov    edx, 1
   mov    ebx,1    ;file descriptor (stdout)
   mov    eax,4    ;system call number (sys_write)
   int    0x80    ;call kernel
    
   mov    eax,1    ;system call number (sys_exit)
   int    0x80    ;call kernel
    
section .data
msg db "The result is:", 0xA,0xD 
len equ $- msg   
segment .bss
res resb 1

编译并执行上述代码后,将产生以下结果-

The result is:
4