彙編 - 數字



數值資料通常以二進位制形式表示。算術指令對二進位制資料進行操作。當數字在螢幕上顯示或從鍵盤輸入時,它們以ASCII碼形式存在。

到目前為止,我們已經將ASCII碼形式的輸入資料轉換為二進位制進行算術計算,並將結果轉換回二進位制。以下程式碼演示了這一點:

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

編譯並執行上述程式碼後,將產生以下結果:

The sum is:
7

但是,這種轉換存在開銷,組合語言程式設計允許以更有效的方式(以二進位制形式)處理數字。十進位制數可以以兩種形式表示:

  • ASCII碼形式
  • BCD碼或二進位制編碼的十進位制形式

ASCII表示

在ASCII表示中,十進位制數儲存為ASCII字元的字串。例如,十進位制值1234儲存為:

31	32	33	34H

其中,31H是1的ASCII值,32H是2的ASCII值,依此類推。有四個指令用於處理ASCII表示中的數字:

  • AAA - 加法後ASCII調整

  • AAS - 減法後ASCII調整

  • AAM - 乘法後ASCII調整

  • AAD - 除法前ASCII調整

這些指令不接受任何運算元,並假定所需的運算數位於AL暫存器中。

以下示例使用AAS指令來演示這個概念:

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  

編譯並執行上述程式碼後,將產生以下結果:

The Result is:
6

BCD表示

BCD表示有兩種型別:

  • 非壓縮BCD表示
  • 壓縮BCD表示

在非壓縮BCD表示中,每個位元組儲存一個十進位制數字的二進位制等價物。例如,數字1234儲存為:

01	02	03	04H

有兩個指令用於處理這些數字:

  • AAM - 乘法後ASCII調整

  • AAD - 除法前ASCII調整

四個ASCII調整指令AAA、AAS、AAM和AAD也可以與非壓縮BCD表示一起使用。在壓縮BCD表示中,每個數字使用四位儲存。兩個十進位制數字打包到一個位元組中。例如,數字1234儲存為:

12	34H

有兩個指令用於處理這些數字:

  • DAA - 加法後十進位制調整

  • DAS - 減法後十進位制調整

壓縮BCD表示不支援乘法和除法。

示例

下面的程式將兩個5位十進位制數相加並顯示總和。它使用了上述概念:

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 '     '

編譯並執行上述程式碼後,將產生以下結果:

The Sum is:
35801
廣告