彙編 - 算術指令



INC 指令

INC 指令用於將運算元加1。它作用於單個運算元,該運算元可以位於暫存器或記憶體中。

語法

INC 指令具有以下語法:

INC destination

運算元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

運算元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 指令:

序號 場景
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(除法)指令用於無符號資料,而 IDIV(整數除法)指令用於有符號資料。

語法

DIV/IDIV 指令的格式:

DIV/IDIV	divisor

被除數在累加器中。這兩個指令都可以處理 8 位、16 位或 32 位運算元。該操作影響所有六個狀態標誌。以下部分解釋了不同運算元大小的三種除法情況:

序號 場景
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
廣告