Si desea llamar a una función de C/C++ de ensamblado en línea, usted puede hacer algo como esto:llamada directa mediante ensamblado en línea de GCC
void callee() {}
void caller()
{
asm("call *%0" : : "r"(callee));
}
GCC entonces emitir código que se parece a esto:
movl $callee, %eax
call *%eax
Esto puede ser problemático ya que la llamada indirecta destruirá la tubería en las CPU más antiguas.
Dado que la dirección de callee
es eventualmente una constante, se puede imaginar que sería posible usar la restricción i
. Citando del CCG en línea 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 trato de utilizar de esta manera:
asm("call %0" : : "i"(callee));
me sale el siguiente error desde el ensamblador:
Error: suffix or operands invalid for `call'
Esto se debe a GCC emite el código
call $callee
En lugar de
call callee
Así que mi pregunta es si es posible hacer que la salida del CCG correcta call
.
¿Estás seguro de que la llamada indirecta destruye la tubería? ¿Has realizado una evaluación comparativa? Tengo entendido que en los viejos días de x86 (pre-i686), las llamadas indirectas eran muy malas (recuerdo que eran 10-100 veces más lentas en mi K6), pero hoy en día las cpus son más inteligentes y pueden manejarlas bien . ¡Entonces haz algunas pruebas antes de saltar a conclusiones! –
@R ..: Tiene razón: si comparo esto con una CPU real, no hace ninguna diferencia. Estoy ejecutando mi código en qemu, sin embargo, y parece hacer una diferencia allí (alrededor de un 20% más ciclos/llamada). – Job
Entonces, simplemente me quedaré con la forma en que lo haces, con la llamada indirecta. Esto permitirá a gcc generar el código correcto para las bibliotecas/ejecutables PIC/PIE sin tener que insertar hacks especiales para manejar estas cosas. –