汇编 - 算术指令

INC指令

INC指令用于将操作数递增1.它适用于可以在寄存器或内存中的单个操作数.

语法

INC指令具有以下语法 :

 
 INC destination

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

示例

 
 INC EBX;增量32位寄存器
 INC DL;增量8位寄存器
 INC [count];递增计数变量

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分别为-bit,16-bit或32-bit操作数.

语法

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(Multiply)指令处理无符号数据,IMUL(整数乘)处理带符号数据.这两条指令都会影响进位和溢出标志.

语法

MUL/IMUL指令的语法如下 :

MUL/IMUL multiplier

两种情况下的乘数都将在累加器中,具体取决于被乘数的大小以及乘数和生成的乘积也存储在两个寄存器中,具体取决于操作数的大小.以下部分解释了具有三种不同情况的MUL指令 :

Sr.No.情景
1

当两个字节相乘 : 去;

被乘数位于AL寄存器中,乘数是存储器或另一个寄存器中的一个字节.该产品在AX中.产品的高阶8位存储在AH中,低阶8位存储在AL中.

Arithmetic1

2

当两个单字值乘以 : 去;

被乘数应该在AX寄存器中,乘数是存储器中的一个字或另一个寄存器.例如,对于像MUL DX这样的指令,必须将乘数存储在DX中,并将被乘数存储在AX中.

结果产品是双字,需要两个寄存器.高阶(最左边)部分存储在DX中,低阶(最右边)部分存储在AX中.

Arithmetic2

3

当两个双字值乘以 : 去;

当两个双字值相乘时,被乘数应该在EAX中,乘数是存储在内存或另一个寄存器中的双字值.生成的产品存储在EDX:EAX寄存器中,即高位32位存储在EDX寄存器中,低位32位存储在EAX寄存器中.

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(Divide)指令用于无符号数据,IDIV(整数除法)用于签名数据.

语法

DIV/IDIV指令的格式 :

DIV/IDIV	divisor

红利在累加器中.这两条指令都可以用于8位,16位或32位操作数.该操作会影响所有六个状态标志.以下部分介绍了具有不同操作数大小和减号的三种除法案例;

Sr.No.情景
1

当除数为1字节 :  

假设被除数在AX寄存器中(16位).除法后,商进入AL寄存器,余数进入AH寄存器.

 Arithmetic4

2

当除数为1字 :  

假设被除数为32位且在DX:AX寄存器中.高阶16位在DX中,低阶16位在AX中.除法后,16位商进入AX寄存器,16位余数进入DX寄存器.

Arithmetic5

3

当除数为双字 :  

假设被除数为64位且在EDX:EAX寄存器.高阶32位在EDX中,低阶32位在EAX中.除法后,32位商进入EAX寄存器,32位余数进入EDX寄存器.

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