В данной заметке я опишу процесс вызова функций Си из ассемблера.
Попробуем вызвать printf(“Hello World!\n”); и exit(0);
section .rodata
message: db "Hello, world!", 10, 0
section .text
extern printf
extern exit
global main
main:
xor rax, rax
mov rdi, message
call printf
xor rdi, rdi
call exit
Все гораздо проще чем кажется, в секции .rodata мы опишем статичные данные, в данном случае строку “Hello, world!”, 10 это символ новой строки, также не забудем занулить ее.
В секции кода объявим внешние функции printf, exit библиотек stdio, stdlib, также объявим функцию входа main:
section .text
extern printf
extern exit
global main
В регистр возврата из функции rax передаем 0, можно использовать mov rax, 0; но для ускорения используют xor rax, rax; Далее в первый аргумент передаем указатель на строку:
rdi, message
Далее вызываем внешнюю функцию Си printf:
main:
xor rax, rax
mov rdi, message
call printf
xor rdi, rdi
call exit
По аналогии делаем передачу 0 в первый аргумент и вызов exit:
xor rdi, rdi
call exit
Как говорят американцы:
Кто никого не слушает
Тот плов кушает @ Александр Пелевин
Источники
https://www.devdungeon.com/content/how-mix-c-and-assembly
https://nekosecurity.com/x86-64-assembly/part-3-nasm-anatomy-syscall-passing-argument
https://www.cs.uaf.edu/2017/fall/cs301/reference/x86_64.html
Исходный код
https://gitlab.com/demensdeum/assembly-playground