🔢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