Ir para conteúdo
  • Cadastre-se
Entre para seguir isso  
fredericopissarra

Criando funções diretamente em assembly no GCC

Posts Recomendados

Não, não estou falando somente do assembly inline, mas de criar uma função inteira em assembly.

Um dos problemas que o GCC, na plataforma x86, tem é que ele não aceita (até a versão 7, pelo menos) o atributo naked numa função. Esse atributo informa ao compilador que ele não deve usar a convenção de chamada e colocar um RET na saída da função. Então, a única forma de fazer isso, ao que parece, é criando uma função em assembly:

; naked.asm
; NASM style

  section .text

  global naked_func
naked_func:
  ; faz qualquer coisa que você quiser aqui...

Eu disse "ao que parece" porque a construção abaixo é possível. E aqui mostro uma simples função que incrementa uma variável global:

/* test.c */
#include <stdio.h>

int g_int = 0;

// não pode ter o qualiificador __volatile__ porque
// o compilador precisa recalcular o offset de g_int
// com base em RIP.
//
// É a mesma coisa que:
//
//  void f( void ) { g_int++; }
//
__asm__ (
  "f:\t\n"
  "  addl $1,g_int(%rip)\t\n"
  "  ret"
);

// O compilador precisa saber que função existe e
// ela é definida aqui como extern para não emitir warnings!
extern void f( void );

int main( void )
{
  f();  // voilà!
  printf( "%d\n", g_int );
}

A função f(), acima, foi construída para o modo x86-64.
Note que a função tem apenas as instruções contidas no bloco __asm__. Poderia ser uma interrupt service routine, por exemplo, e retornar com IRETQ.

Compilando e executando:

$ gcc -O2 -o test test.c
$ ./test
1

Se você listar o código acima, verá que f é definida com apenas as instruções contidas no bloco __asm__!!

Interessante, huh?
 

  • Curtir 3
  • l33t 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Interessante mesmo! Muito obrigado pelo post!

Eu busquei por exemplos de uso do atributo naked, tipo de quando usar, sabe? Encontrei um caso no RTOS pra evitar salvar o contexto duas vezes, um exemplo de ofuscação meio fraco e alguns outros. Por acaso você tem alguns exemplos práticos de uso deste atributo? Tipo, em que situação eu usaria uma função pelada? 🤓

Abraço!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Para evitar que o compilador use a convenção de chamada e/ou coloque um RET no final da função.
Tentei usar uma função naked no GCC porque tentei uma função com atributo interrupt e ele também não suporta (ainda), para o x86.

Agora, no GCC 8.3, naked é suportado para x86... mas eu ainda uso a versão 7.3, default, da minha distro...

Compartilhar este post


Link para o post
Compartilhar em outros sites
48 minutos atrás, fredericopissarra disse:

mas eu ainda uso a versão 7.3, default, da minha distro...

@fredericopissarra que distro usas?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ubuntu... Infelizmente Debian, quando tentei instalar em minha máquina, não funcionou (Dell XPS 8700)... O driver de rede não funfava!
Uso Ubuntu 18.04 aqui porque essas distros são homologadas para máquinas Dell e gosto de distros no estilo Debian.

Eu poderia instalar o pacote gcc-8-multilib-x86-64-linux-gnu, mas não gosto muito de futucar com alguns defaults... Mesmo porque esse pacote é da versão 8.2 que, acho, não implementa atributos naked para x86, ainda...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Join the conversation

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

Visitante
Responder

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons no total são permitidos.

×   Seu link foi automaticamente incorporado.   Mostrar como link

×   Seu conteúdo anterior foi restaurado.   Limpar o editor

×   Não é possível colar imagens diretamente. Carregar ou inserir imagens do URL.

Entre para seguir isso  

  • Quem Está Navegando   0 membros estão online

    Nenhum usuário registrado visualizando esta página.

×
×
  • Criar Novo...