Assembly - Macro

Viết macro là một cách khác để đảm bảo lập trình mô-đun trong hợp ngữ.

  • Macro là một chuỗi các lệnh, được gán bằng tên và có thể được sử dụng ở bất kỳ đâu trong chương trình.

  • Trong NASM, macro được định nghĩa bằng %macro%endmacro các chỉ thị.

  • Macro bắt đầu bằng chỉ thị% macro và kết thúc bằng chỉ thị% endmacro.

Cú pháp để định nghĩa macro -

%macro macro_name  number_of_params
<macro body>
%endmacro

Trong đó, number_of_params chỉ định các tham số số, macro_name chỉ định tên của macro.

Macro được gọi bằng cách sử dụng tên macro cùng với các tham số cần thiết. Khi bạn cần sử dụng một số chuỗi hướng dẫn nhiều lần trong một chương trình, bạn có thể đặt các hướng dẫn đó trong macro và sử dụng nó thay vì viết hướng dẫn mọi lúc.

Ví dụ, một nhu cầu rất phổ biến đối với các chương trình là viết một chuỗi ký tự trên màn hình. Để hiển thị một chuỗi ký tự, bạn cần chuỗi hướng dẫn sau:

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

Trong ví dụ trên về hiển thị một chuỗi ký tự, các thanh ghi EAX, EBX, ECX và EDX đã được sử dụng bởi lệnh gọi hàm INT 80H. Vì vậy, mỗi khi bạn cần hiển thị trên màn hình, bạn cần lưu các thanh ghi này trên ngăn xếp, gọi INT 80H và sau đó khôi phục giá trị ban đầu của các thanh ghi từ ngăn xếp. Vì vậy, có thể hữu ích khi viết hai macro để lưu và khôi phục dữ liệu.

Chúng tôi nhận thấy rằng, một số lệnh như IMUL, IDIV, INT, v.v., cần một số thông tin được lưu trữ trong một số thanh ghi cụ thể và thậm chí trả về giá trị trong một số thanh ghi cụ thể. Nếu chương trình đã sử dụng các thanh ghi đó để lưu giữ dữ liệu quan trọng, thì dữ liệu hiện có từ các thanh ghi này sẽ được lưu trong ngăn xếp và được khôi phục sau khi lệnh được thực thi.

Thí dụ

Ví dụ sau cho thấy việc xác định và sử dụng macro:

; 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

Khi đoạn mã trên được biên dịch và thực thi, nó tạo ra kết quả sau:

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