装配 - 数字
数值数据通常以二进制表示。算术指令对二进制数据进行运算。当数字显示在屏幕上或从键盘输入时,它们都是 ASCII 形式。
到目前为止,我们已经将这些 ASCII 形式的输入数据转换为二进制进行算术计算,并将结果转换回二进制。以下代码显示了这一点 -
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
然而,这种转换有一定的开销,并且汇编语言编程允许以更有效的方式处理二进制形式的数字。十进制数可以用两种形式表示 -
- ASCII 形式
- BCD 或二进制编码的十进制形式
ASCII 表示
在 ASCII 表示中,十进制数存储为 ASCII 字符串。例如,十进制值 1234 存储为 -
31 32 33 34H
其中,31H 为 1 的 ASCII 值,32H 为 2 的 ASCII 值,依此类推。有四个指令用于处理 ASCII 表示的数字 -
AAA - 添加后的 ASCII 调整
AAS - 减法后调整 ASCII
AAM - 乘法后的 ASCII 调整
AAD - 除法前的 ASCII 调整
这些指令不采用任何操作数,并假定所需的操作数位于 AL 寄存器中。
以下示例使用 AAS 指令来演示该概念 -
section .text global _start ;must be declared for using gcc _start: ;tell linker entry point sub ah, ah mov al, '9' sub al, '3' aas or al, 30h mov [res], ax mov edx,len ;message length mov ecx,msg ;message to write mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel mov edx,1 ;message length mov ecx,res ;message to write 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 len equ $ - msg section .bss res resb 1
当上面的代码被编译并执行时,它会产生以下结果 -
The Result is: 6
BCD表示法
BCD 表示法有两种类型 -
- 解压 BCD 表示法
- 压缩 BCD 表示法
在解包 BCD 表示中,每个字节存储十进制数字的二进制等价物。例如,数字 1234 存储为 -
01 02 03 04H
有两个处理这些数字的指令 -
AAM - 乘法后的 ASCII 调整
AAD - 除法前的 ASCII 调整
四个 ASCII 调整指令 AAA、AAS、AAM 和 AAD 也可以与解包 BCD 表示形式一起使用。在压缩 BCD 表示中,每个数字使用四位存储。两个十进制数字被打包成一个字节。例如,数字 1234 存储为 -
12 34H
有两个处理这些数字的指令 -
DAA - 加法后小数调整
DAS - 减法后小数调整
压缩 BCD 表示形式不支持乘法和除法。
例子
以下程序将两个 5 位十进制数相加并显示总和。它使用上述概念 -
section .text global _start ;must be declared for using gcc _start: ;tell linker entry point mov esi, 4 ;pointing to the rightmost digit mov ecx, 5 ;num of digits clc add_loop: mov al, [num1 + esi] adc al, [num2 + esi] aaa pushf or al, 30h popf mov [sum + esi], al dec esi loop add_loop mov edx,len ;message length mov ecx,msg ;message to write mov ebx,1 ;file descriptor (stdout) mov eax,4 ;system call number (sys_write) int 0x80 ;call kernel mov edx,5 ;message length mov ecx,sum ;message to write 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 len equ $ - msg num1 db '12345' num2 db '23456' sum db ' '
当上面的代码被编译并执行时,它会产生以下结果 -
The Sum is: 35801