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