Jump to content
Sign in to follow this  
fredericopissarra

Não recomendo: Usando funções da libc em códigos puramente assembly

 Read 1 minute

Recommended Posts

Posted (edited)
 Read 1 minute

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

Edited by fredericopissarra
Adicionei o texto aqui também, mantendo a fonte. Se puder fazer assim nos próximos, agradeço. Assim a pessoa já clica e lê seu conteúdo, sem precisar clicar em mais um link, mas não deixa de saber a fonte. 👍
  • Curtir 5

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...