Assembly - Số
Dữ liệu số thường được biểu diễn trong hệ thống nhị phân. Các lệnh số học 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.
Cho đến nay, chúng tôi đã chuyển đổi dữ liệu đầu vào này ở dạng ASCII sang nhị phân để tính toán số học và chuyển đổi kết quả trở lại dạng nhị phân. Đoạn mã sau đây cho thấy điều này:
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
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
The sum is:
7
Tuy nhiên, các chuyển đổi như vậy có chi phí cao và lập trình hợp ngữ cho phép xử lý các số theo cách hiệu quả hơn, ở dạng nhị phân. Số thập phân có thể được biểu diễn dưới hai dạng:
- Biểu mẫu ASCII
- BCD hoặc dạng thập phân được mã hóa nhị phân
Biểu diễn ASCII
Trong biểu diễn ASCII, số thập phân được lưu trữ dưới dạng chuỗi ký tự ASCII. Ví dụ: giá trị thập phân 1234 được lưu trữ dưới dạng:
31 32 33 34H
Trong đó, 31H là giá trị ASCII cho 1, 32H là giá trị ASCII cho 2, v.v. Có bốn hướng dẫn để xử lý số trong biểu diễn ASCII -
AAA - Điều chỉnh ASCII sau khi bổ sung
AAS - Điều chỉnh ASCII sau khi trừ
AAM - Điều chỉnh ASCII sau khi nhân
AAD - Điều chỉnh ASCII trước khi phân chia
Các hướng dẫn này không lấy bất kỳ toán hạng nào và giả sử toán hạng bắt buộc phải có trong thanh ghi AL.
Ví dụ sau sử dụng hướng dẫn AAS để chứng minh khái niệm:
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
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
The Result is:
6
Đại diện BCD
Có hai kiểu biểu diễn BCD -
- Biểu diễn BCD được giải nén
- Biểu diễn BCD đóng gói
Trong biểu diễn BCD được giải nén, mỗi byte lưu trữ tương đương nhị phân của một chữ số thập phân. Ví dụ: số 1234 được lưu trữ dưới dạng:
01 02 03 04H
Có hai hướng dẫn để xử lý những con số này -
AAM - Điều chỉnh ASCII sau khi nhân
AAD - Điều chỉnh ASCII trước khi phân chia
Bốn lệnh điều chỉnh ASCII, AAA, AAS, AAM và AAD, cũng có thể được sử dụng với biểu diễn BCD được giải nén. Trong biểu diễn BCD đóng gói, mỗi chữ số được lưu trữ bằng bốn bit. Hai chữ số thập phân được đóng gói thành một byte. Ví dụ: số 1234 được lưu trữ dưới dạng:
12 34H
Có hai hướng dẫn để xử lý những con số này -
DAA - Điều chỉnh thập phân sau khi cộng
DAS - Điều chỉnh số thập phân sau khi trừ
Không hỗ trợ phép nhân và chia trong biểu diễn BCD đóng gói.
Thí dụ
Chương trình sau đây cộng hai số thập phân có 5 chữ số và hiển thị tổng. Nó sử dụng các khái niệm trên -
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 ' '
Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:
The Sum is:
35801