Компоновка и линковка

При стандартной компиляции проекта создается полноценный ELF файл, происходит выравнивание по границам страниц памяти. При использовании указателя global main подключается стартовый код стандартной библиотеки C. 

 Точки входа. 

 Точка входа определяется значением global <что-то> Варианты точек входа. 

 

 

 

 Тип программы 

 Рекомендуемая точка входа 

 Компиляция 

 

 

 

 

 Самостоятельная Linux 

 _start 

 ld 

 

 

 С использованием libc 

 main 

 gcc 

 

 

 GUI Windows 

 WinMain 

 Visual Studio 

 

 

 DLL Windows 

 DllMain 

 Visual Studio 

 

 

 Ядро ОС 

 kmain 

 специальный линкер 

 

 

 Пользовательская 

 любое имя 

 ld -e имя 

 

 

 

 Варианты компиляции 

 Команды консоли 

 nasm -f elf64 hello.asm -o hello.o

ld -o hello hello.o 

 В случае использования точки входа _start 

 make файл 

 hello: hello.o

	gcc -o hello hello.o -no-pie

hello.o: hello.asm

	nasm -f elf64 -g -F dwarf hello.asm -l hello.lst 

 Компилирование происходит командой make, 

 Процедура поиска библиотек 

 Директивой extern printf говорится компилятору: "я знаю где эта функция, делай все остальное".  

 nm -D /lib/x86_64-linux-gnu/libc.so.6 # просмотр списка функций в библиотеке

# Какие библиотеки использует программа

ldd program

# Посмотреть неразрешенные символы в объектном файле

nm -u program.o

# Посмотреть символы в исполняемом файле

nm program | grep printf 

 Объединение нескольких файлов. 

 Вариант 1 - директива include. Она фактически вставляет текст одного файла в другой файл. Например есть файл sum.asm который мы будем включать в файл hello.asm.  

 section .text

; Функция возвращает сумму чисел

; Принимает два параметра:

; rdi - первое число 

; rsi - второе число

; Результат функции возвращается через регистр rax

sum:

 mov rax, rdi ; результат в rax

 add rax, rsi

 ret 

 Тогда hello.asm  

 global _start

 

section .text

%INCLUDE "sum.asm"

_start:

 mov rdi, 33

 mov rsi, 44

 

 call sum

 mov rdi, rax ; для проверки результата помещаем сумму из RAX в RDI

 mov rax, 60

 syscall 

 Вариант 2.  Раздельная компиляция. В этом случае доступные извне метки (функции, данные) объявляются с помощью директивы global. Файл sum.asm:  

 global sum ; делаем функцию sum доступной извне

 

section .text

; Функция возвращает сумму чисел

; Принимает два параметра:

; rdi - первое число 

; rsi - второе число

; Результат функции возвращается через регистр rax

sum:

 mov rax, rdi ; результат в rax

 add rax, rsi

 ret 

 Файл hello.asm  

 global _start

 

extern sum ; функция sum расположена где-то во вне

 

section .text

_start:

 mov rdi, 33

 mov rsi, 44

 

 call sum

 mov rdi, rax ; для проверки результата помещаем сумму из RAX в RDI

 mov rax, 60

 syscall 

 Сначала скомпилируем файл sum.asm:  

 nasm -f elf64 sum.asm -o sum.o 

 Затем скомпилируем файл hello.asm:  

 nasm -f elf64 hello.asm -o hello.o 

 В итоге у нас получится два разных объектных файла - sum.o и hello.o. Скомпонуем их в один исполняемый файл:  

 ld hello.o sum.o -o hello