Ich möchte das Basiszeigerregister verwenden können (%rbp
) innerhalb von Inline-asm. Ein Spielzeugbeispiel dafür ist wie folgt:
void Foo(int &x)
{
asm volatile ("pushq %%rbp;" // 'prologue'
"movq %%rsp, %%rbp;" // 'prologue'
"subq $12, %%rsp;" // make room
"movl $5, -12(%%rbp);" // some asm instruction
"movq %%rbp, %%rsp;" // 'epilogue'
"popq %%rbp;" // 'epilogue'
: : : );
x = 5;
}
int main()
{
int x;
Foo(x);
return 0;
}
Ich hatte das gehofft, da ich die übliche Prolog-/Epilog-Funktionsaufrufmethode verwende, um das Alte zu pushen und zu poppen %rbp
, das wäre ok. Es zeigt jedoch Fehler an, wenn ich versuche, darauf zuzugreifen x
nach dem Inline-Asm.
Der von GCC generierte Assemblercode (leicht abgespeckt) lautet:
_Foo:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
# INLINEASM
pushq %rbp; // prologue
movq %rsp, %rbp; // prologue
subq $12, %rsp; // make room
movl $5, -12(%rbp); // some asm instruction
movq %rbp, %rsp; // epilogue
popq %rbp; // epilogue
# /INLINEASM
movq -8(%rbp), %rax
movl $5, (%rax) // x=5;
popq %rbp
ret
main:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
leaq -4(%rbp), %rax
movq %rax, %rdi
call _Foo
movl $0, %eax
leave
ret
Kann mir jemand sagen, warum dieses Segment fehlerhaft ist? Es scheint, dass ich irgendwie beschädigt %rbp
aber ich sehe nicht wie. Vielen Dank im Voraus.
Ich verwende GCC 4.8.4 auf 64-Bit-Ubuntu 14.04.
Fügen Sie keine Tags nicht verwandter Sprachen hinzu.
– zu ehrlich für diese Seite
29. Dezember 2015 um 22:22 Uhr
Für den Assembler-Code: Verwenden Sie die Assembler-Argumente, um C-seitige Variablen anzugeben; Verlassen Sie sich nicht auf ein bestimmtes Registerlayout im Assemblercode. Und geben Sie immer Clobbers an.
– zu ehrlich für diese Seite
29. Dezember 2015 um 22:24 Uhr
movq %rdi, -8(%rbp)
platziert RDI im Rotbereich. Das tust du dannpushq %rbp;
was dekrementiert UVP durch 8 und setzt den Wert ein RBP dort. Leider seit RSP=RBP Sie haben gerade den Wert überschrieben, den GCC dort gespeichert hat (was vermutlich RDI). Nachdem Ihr Inline-Assembler fertig war, versuchte er esmovq -8(%rbp), %rax
. Nun, wir haben gerade erfahren, dass Sie die Daten am Speicherort vernichtet haben-8(%rbp)
Daher enthält es jetzt einen falschen Wert, und dann versuchen wir, ihn damit zu dereferenzierenmovl $5, (%rax)
. Diese Anweisung ist wahrscheinlich segfaults, weil RAX hat keinen gültigen Zeiger mehr.– Michael Petsch
30. Dezember 2015 um 4:26 Uhr
Wenn Sie C/C++-Variablen innerhalb von Inline-Assembler verwenden möchten, müssen Sie wirklich damit beginnen, Eingabe- (und ggf. Ausgabe-)Einschränkungen zu verwenden, damit Daten ein- (und/oder ausgegeben) werden können.
– Michael Petsch
30. Dezember 2015 um 4:32 Uhr