Assembly組合 巨集


編寫巨集是確保在組合語言模組化程式設計的另一種方式。

  • 巨集是一個指令序列,通過名稱和分配程式可以在任何地方使用。

  • 在NASM中,巨集定義%macro%endmacro指令。

  • 巨集開始%macro指令,結束%endmacro指令。

巨集定義的語法:

%macro macro_name  number_of_params
<macro body>
%endmacro

其中,number_of_params指定數目的引數,macro_name指定巨集名稱。

呼叫巨集時,通過使用巨集的名稱以及必要的引數。當需要使用一些指令序列多次,可以把這些指令在巨集,並用它來代替書面說明。

例如,一個很常見的程式需要在螢幕上寫了一串字元。顯示一串字元,需要下面的指令序列:

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

我們已經觀察到,一些指令IMUL一樣,IDIV,INT等,需要的一些資訊被儲存在一些特定的暫存器,甚至在一些特定的暫存器(次)返回值。如果該程式已經在使用這些暫存器用於儲存重要資料,然後從這些暫存器中的現有資料應儲存在堆疊的指令被執行後,恢復。

在上述範例中,還顯示字串,暫存器EAX,EBX ECX和EDX,我們將使用INT 80H函式呼叫。所以,每次在螢幕上顯示,需要這些暫存器儲存在棧中呼叫INT 80H,然後恢復從堆疊中的暫存器的原始值。因此,它可能是有用的寫兩個巨集用於儲存和恢復資料。

例子:

下面的例子顯示了定義和使用巨集:

; A macro with two parameters
; Implements the write system call
   %macro write_string 2 
      mov   eax, 4
      mov   ebx, 1
      mov   ecx, %1
      mov   edx, %2
      int   80h
   %endmacro
 
section	.text
    global _start            ;must be declared for using gcc
_start:    ;tell linker entry yiibai
	write_string msg1, len1               
	write_string msg2, len2    
	write_string msg3, len3   
	mov eax,1          ;system call number (sys_exit)
	int 0x80           ;call kernel

section	.data
msg1 db	'Hello, programmers!',0xA,0xD 	
len1 equ $ - msg1			
msg2 db 'Welcome to the world of,', 0xA,0xD 
len2 equ $- msg2 
msg3 db 'Linux assembly programming! '
len3 equ $- msg3

上面的程式碼編譯和執行時,它會產生以下結果:

Hello, programmers!
Welcome to the world of,
Linux assembly programming!