Ensamblaje - Números

Los datos numéricos generalmente se representan en sistema binario. Las instrucciones aritméticas operan sobre datos binarios. Cuando los números se muestran en la pantalla o se ingresan desde el teclado, están en formato ASCII.

Hasta ahora, hemos convertido estos datos de entrada en formato ASCII a binarios para cálculos aritméticos y hemos vuelto a convertir el resultado a binario. El siguiente código muestra esto:

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

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

The sum is:
7

Sin embargo, tales conversiones tienen una sobrecarga y la programación en lenguaje ensamblador permite procesar números de una manera más eficiente, en forma binaria. Los números decimales se pueden representar de dos formas:

  • Formulario ASCII
  • Forma decimal codificada en BCD o binaria

Representación ASCII

En la representación ASCII, los números decimales se almacenan como una cadena de caracteres ASCII. Por ejemplo, el valor decimal 1234 se almacena como -

31	32	33	34H

Donde, 31H es el valor ASCII para 1, 32H es el valor ASCII para 2, y así sucesivamente. Hay cuatro instrucciones para procesar números en representación ASCII:

  • AAA - Ajuste ASCII después de la adición

  • AAS - Ajuste ASCII después de la resta

  • AAM - Ajuste ASCII después de la multiplicación

  • AAD - Ajuste ASCII antes de la división

Estas instrucciones no toman ningún operando y asumen que el operando requerido está en el registro AL.

El siguiente ejemplo utiliza la instrucción AAS para demostrar el concepto:

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

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

The Result is:
6

Representación BCD

Hay dos tipos de representación BCD:

  • Representación BCD desempaquetada
  • Representación BCD empaquetada

En la representación BCD descomprimida, cada byte almacena el equivalente binario de un dígito decimal. Por ejemplo, el número 1234 se almacena como -

01	02	03	04H

Hay dos instrucciones para procesar estos números:

  • AAM - Ajuste ASCII después de la multiplicación

  • AAD - Ajuste ASCII antes de la división

Las cuatro instrucciones de ajuste ASCII, AAA, AAS, AAM y AAD, también se pueden utilizar con la representación BCD descomprimida. En la representación BCD empaquetada, cada dígito se almacena utilizando cuatro bits. Se empaquetan dos dígitos decimales en un byte. Por ejemplo, el número 1234 se almacena como -

12	34H

Hay dos instrucciones para procesar estos números:

  • DAA - Ajuste decimal después de la adición

  • DAS - Ajuste decimal después de la resta

No hay soporte para la multiplicación y división en la representación BCD empaquetada.

Ejemplo

El siguiente programa suma dos números decimales de 5 dígitos y muestra la suma. Utiliza los conceptos anteriores:

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 '     '

Cuando se compila y ejecuta el código anterior, produce el siguiente resultado:

The Sum is:
35801