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