汇编 - 数字

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