汇编 - 数字

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