Zgromadzenie - liczby
Dane liczbowe są zwykle przedstawiane w systemie binarnym. Instrukcje arytmetyczne działają na danych binarnych. Liczby wyświetlane na ekranie lub wprowadzane z klawiatury mają postać ASCII.
Do tej pory przekonwertowaliśmy te dane wejściowe w postaci ASCII na binarne do obliczeń arytmetycznych i przekonwertowaliśmy wynik z powrotem na binarny. Poniższy kod pokazuje to -
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
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
The sum is:
7
Takie konwersje mają jednak narzut, a programowanie w języku asemblerowym umożliwia bardziej wydajne przetwarzanie liczb w formie binarnej. Liczby dziesiętne można przedstawić w dwóch formach -
- Formularz ASCII
- BCD lub postać dziesiętna w kodzie binarnym
Reprezentacja ASCII
W reprezentacji ASCII liczby dziesiętne są przechowywane jako ciąg znaków ASCII. Na przykład wartość dziesiętna 1234 jest przechowywana jako -
31 32 33 34H
Gdzie 31H to wartość ASCII dla 1, 32H to wartość ASCII dla 2 i tak dalej. Istnieją cztery instrukcje przetwarzania liczb w reprezentacji ASCII -
AAA - Regulacja ASCII po dodaniu
AAS - Regulacja ASCII po odjęciu
AAM - Regulacja ASCII po pomnożeniu
AAD - Regulacja ASCII przed dzieleniem
Te instrukcje nie pobierają żadnych operandów i zakładają, że wymagany operand znajduje się w rejestrze AL.
W poniższym przykładzie użyto instrukcji AAS, aby zademonstrować koncepcję -
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
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
The Result is:
6
Reprezentacja BCD
Istnieją dwa rodzaje reprezentacji BCD -
- Rozpakowana reprezentacja BCD
- Zapakowana reprezentacja BCD
W rozpakowanej reprezentacji BCD każdy bajt przechowuje binarny odpowiednik cyfry dziesiętnej. Na przykład liczba 1234 jest przechowywana jako -
01 02 03 04H
Istnieją dwie instrukcje dotyczące przetwarzania tych liczb -
AAM - Regulacja ASCII po pomnożeniu
AAD - Regulacja ASCII przed dzieleniem
Cztery instrukcje ASCII, AAA, AAS, AAM i AAD, mogą być również używane z rozpakowaną reprezentacją BCD. W spakowanej reprezentacji BCD każda cyfra jest przechowywana przy użyciu czterech bitów. Dwie cyfry dziesiętne są umieszczane w bajcie. Na przykład liczba 1234 jest przechowywana jako -
12 34H
Istnieją dwie instrukcje dotyczące przetwarzania tych liczb -
DAA - Korekta dziesiętna po dodaniu
DAS - Regulacja dziesiętna po odjęciu
Nie ma obsługi mnożenia i dzielenia w spakowanej reprezentacji BCD.
Przykład
Poniższy program dodaje dwie 5-cyfrowe liczby dziesiętne i wyświetla sumę. Wykorzystuje powyższe koncepcje -
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 ' '
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
The Sum is:
35801