Ir para conteúdo

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


fredericopissarra

Posts Recomendados

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 para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...