宏(Macros)
优质
小牛编辑
129浏览
2023-12-01
编写宏是确保汇编语言模块化编程的另一种方法。
宏是一系列指令,由名称分配,可以在程序中的任何位置使用。
在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等的一些指令需要将一些信息存储在某些特定寄存器中,甚至在某些特定寄存器中返回值。 如果程序已经使用这些寄存器来保存重要数据,那么来自这些寄存器的现有数据应该保存在堆栈中并在执行指令后恢复。
例子 (Example)
以下示例显示了定义和使用宏 -
; 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!