Se si desidera chiamare una funzione C/C++ da assembly inline, si può fare qualcosa di simile:Chiamata diretta tramite l'assembly inline di GCC
void callee() {}
void caller()
{
asm("call *%0" : : "r"(callee));
}
GCC sarà poi emettere il codice che assomiglia a questo:
movl $callee, %eax
call *%eax
Questo può essere problematico poiché la chiamata indiretta distruggerà la pipeline su CPU meno recenti.
Poiché l'indirizzo di callee
è infine una costante, si può immaginare che sarebbe possibile utilizzare il vincolo i
. Citando dal GCC linea 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.
Se cerco di usare in questo modo:
asm("call %0" : : "i"(callee));
ricevo il seguente errore dal assembler:
Error: suffix or operands invalid for `call'
Questo perché GCC emette il codice
call $callee
Invece di
call callee
Quindi la mia domanda è se sia possibile fare uscita GCC il corretto call
.
Sei sicuro che la chiamata indiretta distrugge la pipeline? Hai un benchmark? La mia comprensione era che nei vecchi tempi su x86 (pre-i686), le chiamate indirette erano pessime (ricordo che sono un buon 10-100 volte più lento sul mio K6), ma al giorno d'oggi i cpus sono più intelligenti e riescono a gestirli bene . Quindi fai qualche prova prima di saltare alle conclusioni! –
@R ..: hai ragione: se lo confronto su una CPU reale, non fa alcuna differenza. Sto eseguendo il mio codice in qemu, tuttavia, e sembra fare la differenza lì (circa il 20% in più di cicli/chiamata). – Job
Quindi mi limiterò a seguire il modo in cui lo stai facendo, con la chiamata indiretta. Ciò consentirà a gcc di generare il codice corretto per le librerie/eseguibili PIC/PIE senza dover inserire degli hack speciali per gestire queste cose. –