
彙編 - 算術指令
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 中。 |
2 | 當兩個字值相乘時: 被乘數應在 AX 暫存器中,乘數是記憶體或另一個暫存器中的一個字。例如,對於像 MUL DX 這樣的指令,必須將乘數儲存在 DX 中,將被乘數儲存在 AX 中。 結果乘積是一個雙字,需要兩個暫存器。高位(最左邊)部分儲存在 DX 中,低位(最右邊)部分儲存在 AX 中。 |
3 | 當兩個雙字值相乘時: 當兩個雙字值相乘時,被乘數應在 EAX 中,乘數是儲存在記憶體或另一個暫存器中的一個雙字值。生成的乘積儲存在 EDX:EAX 暫存器中,即高位 32 位儲存在 EDX 暫存器中,低位 32 位儲存在 EAX 暫存器中。 |
示例
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 暫存器。 |
2 | 當除數為 1 字時: 假設被除數為 32 位長,位於 DX:AX 暫存器中。高位 16 位在 DX 中,低位 16 位在 AX 中。除法後,16 位商進入 AX 暫存器,16 位餘數進入 DX 暫存器。 |
3 | 當除數為雙字時: 假設被除數為 64 位長,位於 EDX:EAX 暫存器中。高位 32 位在 EDX 中,低位 32 位在 EAX 中。除法後,32 位商進入 EAX 暫存器,32 位餘數進入 EDX 暫存器。 |
示例
以下示例將 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