汇编 - 数字
数值数据通常以二进制表示。 算术指令对二进制数据进行运算。 当数字显示在屏幕上或从键盘输入时,它们都是 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