🔢Numbers
Dữ liệu số thường được biểu diễn trong hệ thống nhị phân. Arithmetic instructions hoạt động trên dữ liệu nhị phân. Khi các số được hiển thị trên màn hình hoặc được nhập từ bàn phím, chúng ở dạng ASCII (đó là lí do tại sao các bài trước đó tôi đều lưu ý cho bạn là nên xử lí số có 1 chữ số 🤷♂️)
Cho đến nay, chúng tôi đã chuyển đổi input data này ở dạng ASCII sang binary để tính toán số học và chuyển đổi kết quả trở lại binary. Đoạn code sau đây cho thấy điều này:
section .text
global _start
_start:
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
Và điều chắc chắn là:
The sum is:
7
Assembly cho phép xử lý số theo cách hiệu quả hơn, ở dạng binary. Số thập phân có thể được biểu diễn dưới hai dạng:
ASCII form
BCD or Binary Coded Decimal form
ASCII
Trong biểu diễn ASCII, các số thập phân được lưu trữ dưới dạng chuỗi các ký tự ASCII. Ví dụ, giá trị thập phân 1234 được lưu trữ dưới dạng
31 32 33 34h
31
: ASCII value for 1, 32
: ASCII value for 2 và tương tự. Và chúng ta có 4 instructions cho việc xử lí các số được biểu diễn ở dạng ASCII:
AAA − ASCII Adjust After Addition
AAS − ASCII Adjust After Subtraction
AAM − ASCII Adjust After Multiplication
AAD − ASCII Adjust Before Division
Các instructions này không lấy bất kỳ toán hạng nào và giả sử toán hạng cần thiết nằm trong thanh ghi AL. Ví dụ sau sử dụng AAS instruction chứng minh.
section .text
global _start
_start:
sub ah, ah
mov al, '9'
sub al, '3'
aas ; không thay đổi giá trị của các thanh ghi
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
Kết quả của chương trình trên:
The Result is:
6
BCD
Có 2 loại biểu diễn BCD:
Unpacked BCD representation
Packed BCD representation
Trong biểu diễn unpacked BCD, mỗi byte lưu trữ binary tương đương với số thập phân. Ví dụ số 1234 sẽ được lưu trữ như sau:
01 02 03 04H
Có 2 instructions để xử lí những số này:
AAM − ASCII Adjust After Multiplication
AAD − ASCII Adjust Before Division
Có 4 ASCII adjust instructions: AAA, AAS, AAM, AAD có thể được sử dụng với biểu diễn unpacked BCD.
Còn trong packed BCD, mỗi số được lưu trữ 4 bits. 2 chữ số thập phân được packed thành 1 byte. Ví dụ với số 1234:
12 34H
Có 2 instructions dùng để xử lí những số này:
DAA − Decimal Adjust After Addition
DAS − decimal Adjust After Subtraction
Không có hỗ trợ cho phép nhân và chia trong biểu diễn packed BCD
Có vẻ phải có bài tập mới clear hơn được rồi :3
Bài tập:
Viết chương trình cộng 2 số có 5 chữ số (base 10): 18123 và 20103. Sử dụng các phương pháp trên. (Gợi ý: dùng vòng lặp cho từng chữ số)
Nếu bạn thấy khó thì có thể xem đáp án ở phía bên dưới đây.
Lời giải
Khai báo kiểu dữ liệu và biến:
section .data
msg db "Tong cua 2 so do la",0xa
len equ $ - msg
num1 db "18123"
num2 db "20103"
sum db " "
phần xử lí dữ liệu
_start:
mov esi, 4 ;trỏ đến số ngoài cùng bên phải
mov ecx, 5 ;digits of number
add_loop:
mov al, [num1+esi] ;num1[4,3,2,1] --> al
adc al, [num2+esi] ;num2[4,3,2,1] --> al
aaa
or al, 30h
mov [sum + esi], al ;al ---> sum[4,3,2,1]
dec esi
loop add_loop
Sau khi hoàn thiện thì ta có kết quả như đề bài.
Last updated