Nasm에서 콘솔에 출력하는 코드를

만드는 것은 상당히 복잡하기 때문에

직접 만들어서 사용하려면 한계가 있습니다.

 

어셈블리어도 뭔가를 콘솔에

출력해보는 일이 많기 때문에

뭔가 대안이 필요한데요.

 

이럴 때는 '수레바퀴를 새로 발명하지 말라'

(Don't reinvent the wheel) 라는 오랜

프로그래밍 명언을 귀담아 들을 필요가 있습니다.

 

바로 C언어의 printf 함수를 가져와서

사용하는 것 입니다. printf 는 다양한

포맷을 사용할 수 있으니까 유용합니다.

 

%include "utilities.inc"

%macro printString 1
    mov rax, %1
    call _printfString
%endmacro

%macro printInt 1
    mov rax, %1
    call _printfInt
%endmacro

section .data

    text1: db "[NASM Assembly Language]",0
    text2: db "1. call printf function",0

    stringFormat: db "%s",10,0
    integerFormat: db "- value: (%ld)",10,0

section .text
    global main
main:
    printString text1
    printString text2

    printInt 157
    printInt 9567

_last:
    exit

_printfString:
    push rbp
    mov rdi, stringFormat
    mov rsi, rax
    mov rax, 0
    call printf wrt ..plt
    pop rbp
    ret

_printfInt:
    push rbp
    mov rdi, integerFormat
    mov rsi, rax
    mov rax, 0
    call printf wrt ..plt
    pop rbp
    ret

 

NASM printf 함수 C언어 라이브러리

utilities.inc 파일은 합쳐도 상관없는데

메인 파일을 정리하다 보면

자연스럽게 분리가 됩니다.

;C library function
extern printf

;terminate program
%macro exit 0
    mov rax, SYS_EXIT
    mov rdi, EXIT_SUCCESS
    syscall
%endmacro


;Linux system call ID
SYS_READ      equ   0
SYS_WRITE     equ   1
SYS_OPEN      equ   2
SYS_CLOSE     equ   3

SYS_EXIT      equ  60

;file descriptor
STDIN         equ   0
STDOUT        equ   1
STDERR        equ   2

;exit code

EXIT_SUCCESS  equ   0

 

extern printf 가 필요하고

_printfString 을 보면 함수 호출을 위한

rbp 포인터를 스택에 보존했다가

printf 함수가 끝난다음에 다시 복구합니다.

printf 함수의 문자열 포맷을 rdi로 넘깁니다.

rax 는 매크로에서 텍스트를 넘겨주고,

준비가 끝나면 printf 를 호출합니다.

여기서 wrt ..plt 가 없으면 에러가 나더군요.

yasm 메뉴얼에 elf32 스페셜 심볼이라고

되어 있는데 자세한 이유는 모르겠습니다.

아마 64비트에서 printf 를

호출할 때 필요한 듯... 추측합니다.

어셈블리어와 컴파일러는 이해안되는게 많아서;;;

 

9.6. elf32 Special Symbols and WRT (tortall.net)

 

nasm 컴파일 후 gcc로 링크하면 C언어의

printf 함수를 사용할 수 있습니다.

all:
	nasm -f elf64 -o main.o -l main.lst main.asm
	gcc main.o -o main 
	./main

gcc를 사용하는 경우 entry symbol이 _start 가

아니라 main 이어야 인식이됩니다.

 

 

*참고문서

Calling printf from the C standard library in assembly | Mourtada.se

 

Calling printf from the C standard library in assembly

In this post I will show an example how to call the printf function from the C standard library in assembly

www.mourtada.se

 

tutorials/Assembly/Nasm/basics/extern_printf at main · neokayken/tutorials (github.com)

공유하기

facebook twitter kakaoTalk kakaostory naver band