Wenn Sie eine C/C++ Funktion von Inline-Assembler anrufen möchten, können Sie etwas tun:Direktanruf GCC Inline-Montage mit
void callee() {}
void caller()
{
asm("call *%0" : : "r"(callee));
}
GCC wird dann Code emittieren, die wie folgt aussieht:
movl $callee, %eax
call *%eax
Dies kann problematisch sein, da der indirekte Aufruf die Pipeline auf älteren CPUs zerstört.
Da die Adresse callee
schließlich eine Konstante ist, kann man sich vorstellen, dass es möglich wäre, die i
Einschränkung zu verwenden. Zitiert aus der GCC Online 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.
Wenn ich versuche, es zu benutzen, wie folgt aus:
asm("call %0" : : "i"(callee));
ich die folgende Fehlermeldung aus dem Assembler erhalten:
Error: suffix or operands invalid for `call'
Dies liegt daran, GCC sendet den Code
call $callee
Statt
call callee
Also meine Frage ist, ob es möglich ist, GCC Ausgang der korrekten call
zu machen.
Sind Sie sicher, dass der indirekte Aufruf die Pipeline zerstört? Haben Sie ein Benchmarking durchgeführt? Mein Verständnis war, dass in den alten Tagen auf x86 (pre-i686) indirekte Anrufe sehr schlecht waren (ich erinnere mich, dass sie auf meinem K6 10-100 mal langsamer waren), aber heutzutage sind CPUs schlauer und können mit ihnen gut umgehen . Machen Sie also ein paar Tests, bevor Sie voreilige Schlüsse ziehen! –
@R ..: Du hast Recht: Wenn ich das auf einer realen CPU benchze, macht es keinen Unterschied. Ich benutze meinen Code jedoch in qemu und es scheint dort einen Unterschied zu machen (ca. 20% mehr Zyklen/Anruf). – Job
Dann würde ich einfach bei der Art und Weise bleiben, wie Sie es tun, mit dem indirekten Anruf. Dies ermöglicht es gcc, den richtigen Code für PIC/PIE-Bibliotheken/ausführbare Dateien zu erzeugen, ohne dass Sie spezielle Hacks einfügen müssen, um diese Dinge zu handhaben. –