T
Erhard Henkes schrieb:
Frage: Wie kann man dies per XCHG schneller abwickeln, man muss dabei doch auch über die Register?
Mindestens über ein Register, das zweite darf ein Speicherzugriff sein. Die Methode wäre dann also (ebenso AT&T):
movl a, %eax
xchgl %eax, b
xchgl %eax, a
Wenn man den gcc benutzt kann man das noch etwas abkürzen (vom assembelrtext her):
__asm("xchgl %%eax, %1\n\t"
: "=a"(a), "=m"(b)
: "a"(a));
Mit Glück behält der gcc dann a für die weiterverwendung in eax udn man spart ncoh einen gigantösen Befehl
Kann man per Assembler auch auf lokale Variablen in C++ zugreifen. Die befinden sich dort ja im Stack oder auf dem Heap.
Klar, lokale Variablen liegen auf x86 immer aufm Stack. Unter C/C++ ist es folgendermaßen üblich: auf EBP-4 liegt die erste lokale, EBP-8 die zweite (sofern Typ int) etc. Der Code den ich dafür zum Test genommen habe
#include <stdio.h>
int main() {
int a = 1;
int b = 2;
__asm("xchgl %%eax, %1\n\t"
: "=a"(a), "=m"(b)
: "a"(a));
printf("%i %i", a, b);
}
ist z.B. in asm so geworden (AT&T):
main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $1, -4(%ebp)
movl $2, -8(%ebp)
movl -4(%ebp), %eax
#APP
xchgl %eax, -8(%ebp)
#NO_APP
movl %eax, -4(%ebp)
movl -8(%ebp), %eax
movl %eax, 8(%esp)
movl -4(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
leave
ret
Du siehst hier, wie die lokalen Variablen wie -4(%ebp) und -8($bp) (also EBP+4 und EBP+8) angesprochen werden.
NB: Wenn mans optimieren lässt trifft übrigens der erwünschte Effekt ein, dass die Variable a garnicht mehr auf dem Stack rumliegt, sondenr nur noch in eax gehalten wird und der swap so noch kürzer wird:
main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $2, -4(%ebp)
movl $1, %eax
andl $-16, %esp
#APP
xchgl %eax, -4(%ebp)
#NO_APP
movl $.LC0, (%esp)
movl -4(%ebp), %ecx
movl %eax, 4(%esp)
movl %ecx, 8(%esp)
call printf
movl %ebp, %esp
popl %ebp
ret
Man kann es sogar so weit treiben, dass beide Variablen im Register bleiben, aber da wirds dann schwer in g rößeren FUnktionen. Generell ists beim gcc imemr die beste Wahl über die sogenannten Constraints (in diesem Fall "=a"(a) z.B.) Auf die Variablen zuzugreifen, dann kann der gcc selbst entscheiden was im Stack ist und was nicht.