Montagem - Números
Os dados numéricos são geralmente representados no sistema binário. As instruções aritméticas operam com dados binários. Quando os números são exibidos na tela ou inseridos no teclado, eles estão no formato ASCII.
Até agora, convertemos esses dados de entrada no formato ASCII para binário para cálculos aritméticos e convertemos o resultado de volta para binário. O código a seguir mostra isso -
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
Quando o código acima é compilado e executado, ele produz o seguinte resultado -
The sum is:
7
Essas conversões, entretanto, têm uma sobrecarga, e a programação em assembly permite o processamento de números de maneira mais eficiente, na forma binária. Os números decimais podem ser representados em duas formas -
- Formulário ASCII
- BCD ou forma decimal codificada em binário
Representação ASCII
Na representação ASCII, os números decimais são armazenados como string de caracteres ASCII. Por exemplo, o valor decimal 1234 é armazenado como -
31 32 33 34H
Onde 31H é o valor ASCII para 1, 32H é o valor ASCII para 2 e assim por diante. Existem quatro instruções para processar números na representação ASCII -
AAA - Ajuste ASCII após a adição
AAS - Ajuste ASCII após a subtração
AAM - Ajuste ASCII após a multiplicação
AAD - Ajuste ASCII antes da divisão
Estas instruções não levam nenhum operando e assumem que o operando necessário está no registro AL.
O exemplo a seguir usa a instrução AAS para demonstrar o conceito -
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
Quando o código acima é compilado e executado, ele produz o seguinte resultado -
The Result is:
6
Representação BCD
Existem dois tipos de representação BCD -
- Representação BCD descompactada
- Representação BCD embalada
Na representação BCD descompactada, cada byte armazena o equivalente binário de um dígito decimal. Por exemplo, o número 1234 é armazenado como -
01 02 03 04H
Existem duas instruções para processar esses números -
AAM - Ajuste ASCII após a multiplicação
AAD - Ajuste ASCII antes da divisão
As quatro instruções de ajuste ASCII, AAA, AAS, AAM e AAD, também podem ser usadas com representação BCD descompactada. Na representação BCD compactada, cada dígito é armazenado usando quatro bits. Dois dígitos decimais são compactados em um byte. Por exemplo, o número 1234 é armazenado como -
12 34H
Existem duas instruções para processar esses números -
DAA - Ajuste decimal após adição
DAS - Ajuste decimal após a subtração
Não há suporte para multiplicação e divisão na representação BCD compactada.
Exemplo
O programa a seguir adiciona dois números decimais de 5 dígitos e exibe a soma. Ele usa os conceitos acima -
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 ' '
Quando o código acima é compilado e executado, ele produz o seguinte resultado -
The Sum is:
35801