編寫宏是確保在匯編語言模塊化編程的另一種方式。
宏是一個(gè)指令序列,通過名稱和分配程序可以在任何地方使用。
在NASM中,宏定義%macro和%endmacro指令。
宏開始%macro指令,結(jié)束%endmacro指令。
宏定義的語法:
%macro macro_name number_of_params <macro body> %endmacro
其中,number_of_params指定數(shù)目的參數(shù),macro_name指定宏名稱。
調(diào)用宏時(shí),通過使用宏的名稱以及必要的參數(shù)。當(dāng)需要使用一些指令序列多次,可以把這些指令在宏,并用它來代替書面說明。
例如,一個(gè)很常見的程序需要在屏幕上寫了一串字符。顯示一串字符,需要下面的指令序列:
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
我們已經(jīng)觀察到,一些指令I(lǐng)MUL一樣,IDIV,INT等,需要的一些信息被儲(chǔ)存在一些特定的寄存器,甚至在一些特定的寄存器(次)返回值。如果該程序已經(jīng)在使用這些寄存器用于保存重要數(shù)據(jù),然后從這些寄存器中的現(xiàn)有數(shù)據(jù)應(yīng)保存在堆棧的指令被執(zhí)行后,恢復(fù)。
在上述示例中,還顯示字符串,寄存器EAX,EBX ECX和EDX,我們將使用INT 80H函數(shù)調(diào)用。所以,每次在屏幕上顯示,需要這些寄存器保存在棧中調(diào)用INT 80H,然后恢復(fù)從堆棧中的寄存器的原始值。因此,它可能是有用的寫兩個(gè)宏用于保存和恢復(fù)數(shù)據(jù)。
下面的例子顯示了定義和使用宏:
; 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
上面的代碼編譯和執(zhí)行時(shí),它會(huì)產(chǎn)生以下結(jié)果:
Hello, programmers! Welcome to the world of, Linux assembly programming!