汇编语言 算术指令
INC 指令
INC
指令用于将操作数加 1。它对可以在寄存器或内存中的单个操作数起作用。
语法
INC
指令的语法如下:
INC destination
目标操作数 可以是 8 位,16 位或 32 位操作数。
实例
INC EBX ; 32 位寄存器 自增 1
INC DL ; 8 位寄存器 自增 1
INC [count] ; 变量 count 自增 1
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 ;必须声明 gcc
_start: ;告诉链接器入口
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
; 将第一个数字移动到 eax 寄存器,将第二个数字移动至 ebx
; 并减去 ascii 0 将其转换为十进制数
mov eax, [num1]
sub eax, '0'
mov ebx, [num2]
sub ebx, '0'
; 添加 eax 和 ebx
add eax, ebx
; 将 0 添加到以将十进制和转换为 ASCII
add eax, '0'
; 将总和存储在内存位置 res 中
mov [res], eax
; 打印总和
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 ;必须声明 gcc
_start: ;告诉链接器入口
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 ;文件描述 (stdout)
mov eax,4 ;系统调用号 (sys_write)
int 0x80 ;调用内核
mov ecx,sum
mov edx, 1
mov ebx,1 ;文件描述 (stdout)
mov eax,4 ;系统调用号 (sys_write)
int 0x80 ;调用内核
mov eax,1 ;系统调用号 (sys_exit)
int 0x80 ;调用内核
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
在这两种情况下,被乘数都将在一个累加器中,具体取决于被乘数和乘数的大小,并且根据操作数的大小,生成的乘积还将存储在两个寄存器中。
以下部分说明了 3 种不同情况下的 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 ;必须声明 gcc
_start: ;告诉链接器入口点
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 ;文件描述 (stdout)
mov eax,4 ;系统调用号 (sys_write)
int 0x80 ;调用内核
mov ecx,res
mov edx, 1
mov ebx,1 ;文件描述 (stdout)
mov eax,4 ;系统调用号 (sys_write)
int 0x80 ;调用内核
mov eax,1 ;系统调用号 (sys_exit)
int 0x80 ;调用内核
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
(Divide)指令用于无符号数据,IDIV
(整数除法)用于有符号数据。
语法
DIV
/ IDIV
指令的格式:
DIV/IDIV divisor
被除数在累加器中。两条指令都可以使用 8 位,16 位或 32 位操作数。该操作影响所有 6 个状态标志。
以下部分说明了 3 种操作数大小不同的除法情况:
编号 | 情景 |
---|---|
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 ;必须声明 gcc
_start: ;告诉链接器入口点
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 ;文件描述 (stdout)
mov eax,4 ;系统调用号 (sys_write)
int 0x80 ;调用内核
mov ecx,res
mov edx, 1
mov ebx,1 ;文件描述 (stdout)
mov eax,4 ;系统调用号 (sys_write)
int 0x80 ;调用内核
mov eax,1 ;系统调用号 (sys_exit)
int 0x80 ;调用内核
section .data
msg db "The result is:", 0xA,0xD
len equ $- msg
segment .bss
res resb 1
结果如下:
The result is:
4