Si vous voulez appeler une fonction C/C++ de l'assemblage en ligne, vous pouvez faire quelque chose comme ceci:appel direct à l'aide de l'assembleur en ligne de GCC
void callee() {}
void caller()
{
asm("call *%0" : : "r"(callee));
}
GCC émettra alors un code qui ressemble à ceci:
movl $callee, %eax
call *%eax
Cela peut être problématique car l'appel indirect détruira le pipeline sur les anciennes UC. Comme l'adresse de callee
est éventuellement une constante, on peut imaginer qu'il serait possible d'utiliser la contrainte i
. Je cite le CCG en ligne docs:
`i'
An immediate integer operand (one with constant value) is allowed. This includes symbolic constants whose values will be known only at assembly time or later.
Si j'essaie de l'utiliser comme ceci:
asm("call %0" : : "i"(callee));
que je reçois l'erreur suivante de l'assembleur:
Error: suffix or operands invalid for `call'
C'est parce que GCC émet le code
call $callee
Au lieu de
call callee
Donc, ma question est de savoir s'il est possible de faire la production de GCC l'call
correcte.
Etes-vous sûr que l'appel indirect détruit le pipeline? Avez-vous évalué? Ma compréhension était que dans les vieux jours sur x86 (pré-i686), les appels indirects étaient très mauvais (je me souviens qu'ils sont un bon 10-100 fois plus lent sur mon K6), mais de nos jours, les processeurs sont plus intelligents et peuvent les gérer . Alors faites quelques tests avant de sauter aux conclusions! –
@R ..: Vous avez raison: si je compare cela à un vrai CPU, cela ne fait aucune différence. Je cours mon code en qemu, cependant, et il semble faire une différence là-bas (environ 20% plus de cycles/appel). – Job
Ensuite, je voudrais juste coller à la façon dont vous le faites, avec l'appel indirect. Cela permettra à gcc de générer le code correct pour les bibliothèques/exécutables PIC/PIE sans avoir à insérer des hacks spéciaux pour gérer ces choses. –