彙編 - 宏



編寫宏是確保組合語言中模組化程式設計的另一種方法。

  • 宏是一系列指令,由名稱分配,可以在程式中的任何位置使用。

  • 在 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

在上面顯示字元字串的示例中,INT 80H 函式呼叫使用了暫存器 EAX、EBX、ECX 和 EDX。因此,每次您需要在螢幕上顯示時,都需要將這些暫存器儲存在堆疊中,呼叫 INT 80H,然後從堆疊中恢復暫存器的原始值。因此,編寫兩個用於儲存和恢復資料的宏可能很有用。

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

示例

以下示例顯示了定義和使用宏:

; 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 point
   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!
廣告