Написание макроса — это еще один способ обеспечения модульного программирования на ассемблере.
-
Макрос — это последовательность инструкций, присваиваемая именем и может использоваться в любом месте программы.
-
В NASM макросы определяются с помощью директив % macro и % endmacro .
-
Макрос начинается с директивы% macro и заканчивается директивой% endmacro.
Макрос — это последовательность инструкций, присваиваемая именем и может использоваться в любом месте программы.
В 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
В приведенном выше примере отображения строки символов регистры 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
Когда приведенный выше код компилируется и выполняется, он дает следующий результат —