📜  程序集-宏

📅  最后修改于: 2020-11-05 05:10:04             🧑  作者: Mango


编写宏是确保使用汇编语言进行模块化编程的另一种方法。

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

  • 在NASM中,宏使用%macro%endmacro指令定义。

  • 宏以%macro指令开头,以%endmacro指令结尾。

宏定义的语法-

%macro macro_name  number_of_params

%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

在显示的上述例子中,寄存器EAX,EBX,ECX EDX和已经使用由INT 80H函数调用。因此,每次需要在屏幕上显示时,都需要将这些寄存器保存在堆栈中,调用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!