fredericopissarra Posted April 27, 2020 at 11:31 AM Share Posted April 27, 2020 at 11:31 AM Sempre topo com essa questão em foruns e mídias como o Discord: Como usar funções da biblioteca padrão de C em códigos puramente escritos em assembly? É “fácil”, mas eu não recomendo. Primeiro mostrarei como, usando o NASM e o GCC e depois digo o por quê da não recomendação. Eis um “hello, world” simples: ; test.asm ; Compile com: ; nasm -felf64 -o test.o test.asm bits 64 ; A glibc exige "RIP relative addressing". ; De qualquer maneira, isso é sempre uma boa ; prática no modo x86-64. default rel section .rodata msg: db `hello, world`,0 section .text ; Este símbolo está na glibc! extern puts global main main: ; Chama puts(), passando o ponteiro da string. lea rdi,[msg] call puts wrt ..plt ; return 0; xor eax,eax ret O código acima é diretamente equivalente a: #include <stdio.h> int main( void ) { puts( "hello, world" ); return 0; } Para compilar, linkar e testar: $ nasm -felf64 -o test.o test.asm $ gcc -o test test.o $ ./test hello, world Simples assim. O gcc deve ser usado como linker porque ele sabe onde a libc está. O wrt ..plt é um operador do NASM chamado With Reference To. Ele diz que o símbolo está localizado em uma section específica. No caso a section ..plt, que contém os saltos para as funções da libc (late binding). Isso é necessário, senão obterá um erro de linkagem porque o linker não encontrará o símbolo… PLT é a sigla de “Procedure Linkage Table“. É uma tabela com ponteiros para as funções carregadas dinamicamente da libc. Eis o porque de minha não recomendação: O compilador nem sempre usa o nome “oficial” da função, que pode ser um #define num header e, ás vezes, existem argumentos adicionais “invisíveis” para certas funções “intrínsecas”, mas o principal argumento contra essa prática é que seu código não ficará menor ou mais rápido só porque você está usando assembly. Por exemplo, ambos os códigos em C e Assembly, acima, fazem exatamente a mesma coisa e têm o mesmíssimo tamanho final (6 KiB, extirpando os códigos de debbugging e stack protection, no caso de C). De fato, é provável que você crie um código em assembly pior do que o compilador C criaria… Addedum: Não recomendo, particularmente, que se tente escrever códigos em assembly que usem a libc no ambiente Windows. O problema é que Windows coloca algum código adicional nas funções. Por exemplo, A pilha deve ser alterada para acomodar SEH (Structured Exception Handling), no caso de main, é necessário chamar uma função chamada _main… Coisas assim são problemáticas para o novato. Fonte: Lá no #BitIsMyth: https://wp.me/pudbF-1RF Link to comment Share on other sites More sharing options...
fredericopissarra Posted April 27, 2020 at 07:32 PM Author Share Posted April 27, 2020 at 07:32 PM PS: O código acima usa SysV x86-64 ABI (só funciona em 'unixes'). O do Windows é diferente (vide Addendum). Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.