카테고리

asm (27) bootloader_x86_grub (1) C (92) compile (11) config (76) CPP (13) CSS (1) debugging (7) gimp (1) Go (1) html (1) Java (1) JavaScript (1) kernel (19) LibreOffice (3) Linux system progamming (21) MFC (1) opencv (4) OpenGL (1) PHP (1) Python (4) qemu (29) shell (3) socket (7) troubleshooting (2) ubuntu18.04 (2) windows (1)

2018/12/29

리눅스 어셈블리의 nasm x86_64 매크로

리눅스 어셈블리의 nasm x86_64 매크로

1. 매크로란?

매크로는 특정 작업을 수행 하기 위해 미리 정의된 명령어 모음에 대한 확장 되는 단일 명령어.

exit:
 mov rax, 60
 mov rdi, 0
 syscall

2. 매크로 정의
<name>
  매크로 이름.
<argc>
  매크로 동작 인수의 갯수.
<macro body>
매크로 정의.

%macro <name> <argc>
...
<macro body>
...
%endmacro

"Exit" Macro

%macro exit 0 ; 0은 argc 인수의 개수
mov rax, 60
mov rdi, 0
syscall
%endmacro

3. 매크로 인수
<argc> 매크로에 사용하는 인수의 개수이다. 인수는 매크로로 전달 될 수 있다.

매크로 본문 내에서 이러한 입력은 첫 번째 입력에 대해 '%1', 즉 두 번째 입력에 대해 '%2'를 사용 하여 참조 된댜.

%macro <name> <argc>
...
<macro body>
...
%endmacro

"printDigit" 매크로의 경우 argc는 1이다.

"exit" 매크로의 경우 argc는 인수가 없기 때문에 0이다.

_start 아래의 코드에서 "printdigit"를 사용 하면 첫 번째 인수 뒤에 숫자를 지정.

현재 사용 하는 "exit" 인수가 0이기 때문에 숫자를 지정 하지 않는다.

%macro exit 0
mov rax, 60
mov rdi, 0
syscall
%endmacro

%macro printDigit 1
mov rax, %1
call _printRAXDigit
%endmacro

_start:
printDigit 3
printDigit 4

exit

This code will print "3" then "4"
http://pastebin.com/5K3CARnw

args > 1 인 경우, 입력 구분자로 쉼표 사용.

%macro printDigitSum 2
mov rax, %1
add rax, %2
call _printRAXDigit
$endmacro

_start:
printDigitSum 3,2
exit

이 코드는 "5" 출력.

4. 매크로 로컬 레이블
매크로는 미리 정의된 코드로 컴파일 할 때 확장 된다.
해당 코드에 레이블이 포함 된 경우 매크로가 두 번 이상 사용되면 중복된 레이블 오류가 발생할 수 있다.

%macro freeze 0
_loop:
jmp _loop
%endmacro

_start:
freeze
freeze
exit

;Redefined Symbol Error
_loop:
jmp _loop

_loop:
jmp _loop
exit


이 문제는 매크로 내에서 레이블 이름 앞에 "%%"를 사용 하여 해결할 수 있다.
이렇게 하면 레이블 확장시 사용할 수 있다.

%macro freeze 0 ---> %macro freeze 0
_loop: ---> %%loop:
jmp _loop ---> jmp %%loop
%endmacro ---> %endmacro


5. EQU 값 정의
EQU는 나중에 사용할 상수를 정의 하는데 사용.

section .data
test db "Hello, World!",10

section .text
global _start

_start:
mov rax, 1
mov rdi, 1
mov rsi, text
mov rdx, 14
syscall

mov rax, 60
mov rdi, 0
syscall

STDIN equ 0
STDOUT equ 1
STDERR equ 2

SYS_READ equ 0
SYS_WRITE equ 1
SYS_EXIT equ 60

section .data
text db "Hello, World!",10

section .text
global _start

_start:
mov rax, SYS_WRITE
mov rdi, STDOUT
mov rsi, text
mov rdx, 14
syscall

mov rax, SYS_EXIT
mov rdi, 0
syscall

6. 외부 파일 포함
단일 어셈블리 프로그램은 "include"를 사용하여 여러 파일로 나눌 수 있다.

"include"는 외부 파일의 코드를 로드하여 포함 된 위치에 추가한다.

매크로와 EQU 정의는 포함(include)된 파일 내부에 있다.
%include "filename.asm"

"Hello, World!" 코드는 'linux64.inc' 파일에 이미 정의되어 있는 'print' 및 'exit' 매크로를 통해 동작 한다.
%include "linux64.inc"

section .data
text db "Hello, World!",10,0

section .text
global _start

_start:
print text
exit

"linux64.inc"
http://pastebin.com/N1ZdmhLw

댓글 없음:

댓글 쓰기