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