Se uma syscall precisa de alguns argumentos de 32 bits como uid_t
ou int
(para descritores de arquivo) unsigned int
ou mesmo algum tipo de 16 bits, como posso passá-los usando registradores de 64 bits?
Preciso estender zero ou estender sinal para 64 bits antes de usar a syscall
instrução?
E se eu usar __X32_SYSCALL_BIT
no RAX para que o argumento do tipo ponteiro de 64 bits original se torne 32 bits, ainda preciso usar o mesmo registro de 64 bits para passar o argumento, preciso estender zero argumentos de endereço nesses casos?
Você deve estendê-los a zero, mas para o caso comum de valores de 32 bits em x86-64, não há necessidade de pensar nisso: armazenar um valor em um registrador de 32 bits resulta em um armazenamento estendido de zero para o registrador de 64 bits correspondente ( ou seja ,
movl $4, %edx
armazena 4 emrdx
). Os valores de 8 e 16 bits devem ser explicitamente estendidos para zero (movzbl
oumovzwl
de um registrador de 8 ou 16 bits para um registrador de 32 bits, implicitamente estendido para 64 bits).Na prática, para não-ponteiros, a implementação da chamada do sistema lerá apenas os n bits mais baixos de qualquer maneira, então você não deve ver nenhuma diferença prática, pelo menos para valores de 32 bits. ( Por exemplo , chamar
SYS_read
com lixo nos 32 bits superioresRDI
não produz um erro, e só leva em consideração os 32 bits inferiores.) Eu não verifiquei o que acontece se você definir__X32_SYSCALL_BIT
sem limpar os 32 bits superiores de ponteiros.