Quais são as convenções de chamada para chamadas do sistema UNIX e Linux em i386 e x86-64?

Os links a seguir explicam as convenções de chamada do sistema x86-32 para UNIX (versão BSD) e Linux:

  • http://www.int80h.org/bsdasm/#system-calls

  • http://www.freebsd.org/doc/en/books/developers-handbook/x86-system-calls.html

Mas quais são as convenções de chamada do sistema x86-64 no UNIX e Linux?

Eu verifiquei isso usando o GNU Assembler (gás) no Linux.

Interface do Kernel

Convenção de Chamada do Sistema Linux x86-32:

Em x86-32 parâmetros para o sistema Linux, as chamadas são passadas usando registradores. %eax para syscall_number. % ebx,% ecx,% edx,% esi,% edi,% ebp são usados ​​para passar 6 parâmetros para as chamadas do sistema.

O valor de retorno está em %eax . Todos os outros registradores (incluindo EFLAGS) são preservados no int $0x80 .

Eu peguei o seguinte trecho do Linux Assembly Tutorial, mas tenho dúvidas sobre isso. Se qualquer um puder mostrar um exemplo, seria ótimo.

Se houver mais de seis argumentos, %ebx deverá conter o local da memory onde a lista de argumentos está armazenada – mas não se preocupe, pois é improvável que você use um syscall com mais de seis argumentos.

Para um exemplo e um pouco mais de leitura, consulte http://www.int80h.org/bsdasm/#alternate-calling-convention

Existe uma maneira mais rápida de fazer chamadas de sistema de 32 bits: usando o sysenter . O kernel mapeia uma página de memory em cada processo (o vdso), com o lado do espaço de usuário do sysenter , que tem que cooperar com o kernel para que ele possa encontrar o endereço de retorno. arg para registrar o mapeamento é o mesmo que para int $0x80 , mas ao invés daquela instrução, o código deve chamar uma function no vdso. (TODO: atualize isso com um link e / ou informações específicas).

x86-32 [Free | Open | Net | DragonFly] Convenção de chamada do sistema BSD UNIX:

parameters são passados ​​na pilha. Empurre os parâmetros (último parâmetro pressionado primeiro) para a pilha. Em seguida, empurre um adicional de 32 bits de dados fictícios (não é realmente dados fictícios. Consulte o link a seguir para obter mais informações) e, em seguida, dar uma instrução de chamada do sistema int $0x80

http://www.int80h.org/bsdasm/#default-calling-convention


Convenção de chamada do sistema Linux x86-64:

x86-64 O Mac OS X é semelhante, mas diferente . TODO: verifique o que o * BSD faz.

Consulte a seção: “A.2 Convenções do kernel Linux AMD64″ da interface binária de aplicativos do System V Suplemento do processador de arquitetura AMD64 . As versões mais recentes dos psABIs i386 e x86-64 System V podem ser encontradas a partir desta página no repository do mantenedor ABI . (Veja também o wiki da tag x86 para links ABI atualizados e muitas outras coisas boas sobre x86 asm.)

Aqui está o trecho desta seção:

  1. Aplicativos de nível de usuário usam como registradores de inteiros para passar a seqüência% rdi,% rsi,% rdx,% rcx,% r8 e% r9. A interface do kernel usa% rdi,% rsi,% rdx,% r10,% r8 e% r9.
  2. Uma chamada de sistema é feita através da instrução syscall . Este clobbers% rcx e% r11, bem como% rax, mas outros registradores são preservados.
  3. O número do syscall deve ser passado no registrador% rax.
  4. Chamadas de sistema são limitadas a seis argumentos, nenhum argumento é passado diretamente na pilha.
  5. Retornando do syscall, registre% rax contendo o resultado da chamada do sistema. Um valor no intervalo entre -4095 e -1 indica um erro, é -errno .
  6. Somente valores de class INTEGER ou class MEMORY são passados ​​para o kernel.

Lembre-se que isto é do apêndice específico do Linux para o ABI, e mesmo para o Linux é informativo não normativo. (Mas é de fato preciso.)

Interface de usuário

Convenção de chamada de function x86-32:

Em x86-32 parâmetros foram passados ​​na pilha. Último parâmetro foi empurrado primeiro para a pilha até que todos os parâmetros sejam feitos e, em seguida, a instrução de call foi executada. Isso é usado para chamar funções da biblioteca C (libc) no Linux a partir do assembly.


Convenção de chamada da function x86-64:

x86-64 passa args nos registradores, o que é mais eficiente que a convenção args de pilha do System V. Isso evita a latência e instruções extras de armazenar argumentos na memory (cache) e, em seguida, os carrega novamente no receptor. Isso funciona bem porque há mais registros disponíveis e é melhor para CPUs modernas de alto desempenho, nas quais a latência e a execução fora de ordem são importantes. (O i386 ABI é muito antigo).

Nesse novo mecanismo: primeiro os parâmetros são divididos em classs. A class de cada parâmetro determina a maneira pela qual ele é passado para a function chamada.

Para obter informações completas, consulte: “3.2 Sequência de Chamada de Função” da Interface Binária de Aplicação do Sistema V Suplemento do Processador de Arquitetura AMD64 que lê, em parte:

Depois que os argumentos são classificados, os registradores são atribuídos (na ordem da esquerda para a direita) para passar da seguinte maneira:

  1. Se a class for MEMORY, passe o argumento na pilha.
  2. Se a class for INTEGER, o próximo registro disponível da sequência% rdi,% rsi,% rdx,% rcx,% r8 e% r9 será usado

Então %rdi, %rsi, %rdx, %rcx, %r8 and %r9 são os registradores em ordem usados ​​para passar os parâmetros inteiro / ponteiro (ie class INTEGER) para qualquer function libc da assembly. % rdi é usado para o primeiro parâmetro INTEGER. % rsi para 2º,% rdx para 3º e assim por diante. Então call instrução deve ser dada. A pilha ( %rsp ) deve estar alinhada com 16B quando a call executada.

Se houver mais de 6 parâmetros INTEGER, o parâmetro 7th INTEGER e mais tarde serão passados ​​na pilha. (Chamador aparece, mesmo como x86-32.)

Os primeiros 8 argumentos de ponto flutuante são passados ​​em% xmm0-7, posteriormente na pilha. Não há registros vetoriais preservados por chamada. (Uma function com uma mistura de argumentos FP e inteiros pode ter mais de 8 argumentos de registro total.)

Funções variadicas ( como printf ) sempre precisam de %al = o número de argumentos de registro de FP.

Existem regras para quando empacotar estruturas em registradores ( rdx:rax no retorno) vs. na memory. Veja a ABI para detalhes, e verifique a saída do compilador para certificar-se de que seu código concorda com os compiladores sobre como algo deve ser passado / retornado.

Talvez você esteja procurando pela ABI x86_64?

Se isso não for exatamente o que você procura, use ‘x86_64 abi’ em seu mecanismo de pesquisa preferido para encontrar referências alternativas.

As convenções de chamada definem como os parâmetros são passados ​​nos registros ao chamar ou ser chamado por outro programa. E a melhor fonte dessas convenções é na forma de padrões ABI definidos para cada um desses hardwares. Para facilitar a compilation, o mesmo ABI também é usado pelo userspace e pelo programa kernel. Linux / Freebsd seguem o mesmo ABI para x86-64 e outro conjunto para 32 bits. Mas o x86-64 ABI for Windows é diferente do Linux / FreeBSD. E, geralmente, a ABI não diferencia a chamada do sistema em comparação com as “chamadas de funções” normais. Ou seja, aqui está um exemplo particular de convenções de chamada x86_64 e é o mesmo para o espaço de usuário e kernel do Linux: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64 / (observe a sequência a, b, c, d, e, f dos parâmetros):

Uma boa renderização de convenções de chamada versus uso de registros

O desempenho é uma das razões para estes ABI (por exemplo, passando parâmetros através de registros em vez de salvar em pilhas de memory)

Para o ARM há vários ABI:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.subset.swdev.abi/index.html

https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/iPhoneOSABIReference.pdf

Convenção ARM64:

http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf

Para Linux no PowerPC:

http://refspecs.freestandards.org/elf/elfspec_ppc.pdf

http://www.0x04.net/doc/elf/psABI-ppc64.pdf

E para incorporado existe o PPC EABI:

http://www.freescale.com/files/32bit/doc/app_note/PPCEABI.pdf

Este documento é uma boa visão geral de todas as diferentes convenções:

http://www.agner.org/optimize/calling_conventions.pdf

Além do link que Jonathan Leffler fornece em sua resposta, também as convenções de chamada do Agner Fog podem ser úteis para você.

Intereting Posts