비트와 자장가

x86_64 어셈블리어 링킹linking 본문

개발/자료

x86_64 어셈블리어 링킹linking

eastriver 2021. 3. 29. 20:45
728x90

아래는 시스템콜 write를 호출해 "hello world"와 개행문자를 출력하는 간단한 C 프로그램이다:

#include <unistd.h>

int main()
{
	write(1, "hello world\n", 12);
}
gcc hello.c && ./a.out

위를 맥용 어셈블리어로 바꾸면 아래와 같다:

	global	start

	section	.text
start:
	mov	rax, 0x02000004		;write()
	mov	rdi, 1
	mov	rsi, string
	mov	rdx, 12
	syscall
	mov	rax, 0x02000001		;exit()
	xor	rdi, rdi
	syscall

	section	.data
string:
	db	"hello world",10	;"hello world\n"
nasm -f macho64 hello.s && ld -static hello.o && ./a.out

위의 명령이 어떠한 경고도 뜨지 않고 제일 간단하다.

 

리눅스에서는 write의 주소로 0x02000004 대신 1, exit의 주소로 0x02000001 대신 60을 사용하여, 아래의 명령으로 실행 가능하다.

nasm -f elf64 hello.s && ld hello.o && ./a.out

맥OS 빅서 11.0.1 에서부터 다이나믹 라이브러리의 위치가 달라져 링킹의 방식도 달라졌다.

위의 방식 외에도 ld의 링킹 명령을 다음으로 대체 가능하다:

ld hello.o -macosx_version_min 11.0 -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lSystem
ld hello.o -macosx_version_min 10.7

하지만 11.0 이전 버전의 링킹은 deprecated 되었으므로 사용하지 말자.

	global	_main

	section	.text
_main:
	mov	rax, 0x02000004
	mov	rdi, 1
	mov	rsi, string
	mov	rdx, 12
	syscall
	mov	rax, 0x02000001
	xor	rdi, rdi
	syscall

	section	.data
string:
	db	"hello world",10

_main 라벨을 사용하면 ld 대신 gcc로 바로 링킹해도 된다(gcc가 알아서 ld를 사용해주므로).

nasm -f macho64 hello.s && gcc hello.o && ./a.out

start나 _main 말고 아무 라벨을 붙이고 엔트리 포인트를 그곳으로 직접 지정하는 방법도 있다.

	global	hello

	section	.text
hello:
	mov	rax, 0x02000004
	mov	rdi, 1
	mov	rsi, string
	mov	rdx, 12
	syscall
	mov	rax, 0x02000001
	xor	rdi, rdi
	syscall

	section	.data
string:
	db	"hello world",10
nasm -f macho64 hello.s && ld -static -e hello hello.o && ./a.out

 

728x90
반응형
Comments