2010-01-22 4 views
32

Ich erinnere mich daran, einen Weg gesehen zu haben, erweiterte gcc-Inline-Assembly zu verwenden, um einen Registerwert zu lesen und in einer C-Variablen zu speichern. Ich kann mich jedoch nicht für das Leben von mir daran erinnern, wie ich die asm-Aussage formulieren soll. Jede Hilfe wird sehr geschätzt.Lesen eines Registerwerts in eine C-Variable

+1

Und wie Sie wissen, was in EBX ist, wenn Ihr C-Code ausgeführt beginnt? – florin

Antwort

0

Ist nicht this nach was Sie suchen?

Syntax:

asm ("fsinx %1,%0" : "=f" (result) : "f" (angle)); 
+0

Sie wissen, dass das eine Variable lesen wird, berechnen Sie den Sinus und speichern Sie das Ergebnis in einer zweiten Variablen. –

+0

@ Samuel: Das war nur ein Beispiel für die Syntax. –

+0

Downvoted, weil dies ein Beispiel dafür ist, wie die erweiterte Assembly in GCC verwendet wird, und nicht, wie der Wert eines bestimmten Registers in eine bestimmte Variable gebracht wird, was das OP angefordert hat. Durch Angabe der Register mit '% 0' und'% 1' wählt GCC das betreffende Register für Sie aus. Es gibt keine Versicherung, dass es das Register wählen wird, auf das Sie hoffen. –

5

Ich weiß nicht, über gcc, aber in VS dies ist, wie:

int data = 0; 
__asm 
{ 
    mov ebx, 30 
    mov data, ebx 
} 
cout<<data; 

Im Wesentlichen habe ich die Daten in ebx auf Ihre Variable data bewegt.

+0

x86 nur natürlich. Microsofts Compiler für x64 und Itanium unterstützen keine Inline-Assemblierung. – ephemient

+0

Ich denke, die Baugruppe wird übersetzt in mov ebx, 30 mov dword ptr [Daten], ebx – Sridarshan

+2

Warum nicht nur 'mov Daten, 30'? – Houssni

17

Hier ist ein Weg, ebx zu erhalten:

int main() 
{ 
    int i; 
    asm("\t movl %%ebx,%0" : "=r"(i)); 
    return i + 1; 
} 

Das Ergebnis:

main: 
    subl $4, %esp 
    #APP 
      movl %ebx,%eax 
    #NO_APP 
    incl %eax 
    addl $4, %esp 
    ret 


Edit:

Die "= r" (i) eine Ausgabebedingung, dem Compiler mitteilen, dass die erste Ausgabe (% 0) ein Register ist, das in die Variable "i" eingefügt werden soll. Bei dieser Optimierungsebene (-O5) wird die Variable i niemals im Speicher gespeichert, sondern im eax-Register, das auch das Rückgabewertregister ist.

+1

Ich würde die Bedingung "= rm" anstelle von "= r" verwenden. Der Optimierer des Compilers versucht, den besten Pfad auszuwählen. Wenn sich der Inline-Assembler zufällig in einer Situation befindet, in der ein Register ausgehungert ist, kann "= r" dazu führen, dass er weniger als optimalen Code generiert. '= rm' würde dem Optimierer die Möglichkeit geben, eine Speicherreferenz zu verwenden, wenn dies die beste Wahl wäre. In diesem einfachen Beispiel ist dies kein Problem, aber wenn sich der Code in einer komplexeren Situation befindet, kann es nützlich sein, dem Compiler Optionen zu geben. –

2

Dadurch wird das Stapelzeigerregister in die Variable sp verschoben.

intptr_t sp; 
asm ("movl %%esp, %0" : "=r" (sp)); 

Ersetzen Sie einfach ‚esp‘ mit dem eigentlichen registrieren Sie interessiert sind (aber stellen Sie sicher nicht die %% zu verlieren) und ‚sp‘ mit Variable.

28

Gehen in eine andere Richtung als andere Antworten bisher, da ich nicht sicher bin, was Sie wollen.

GCC Manual § 5.40 Variables in Specified Registers

register int *foo asm ("a5"); 

Hier a5 ist der Name des Registers, das verwendet werden soll & hellip;

Natürlich ist der Registername CPU-abhängig, aber das ist kein Problem, da spezifische Register meistens mit expliziten Assemblerbefehlen nützlich sind (siehe Extended Asm). Beide dieser Dinge erfordern im Allgemeinen, dass Sie Ihr Programm abhängig vom CPU-Typ konditionieren.

Die Definition einer solchen Registervariable reserviert das Register nicht; Es bleibt für andere Verwendungszwecke an Orten verfügbar, an denen die Flusssteuerung feststellt, dass der Wert der Variablen nicht aktiv ist.

GCC Manual § 3.18 Options for Code Generation Conventions

-ffixed-reg

das Register Treat genannt reg als festes Register; Generierter Code sollte sich niemals darauf beziehen (außer vielleicht als Stack-Pointer, Frame-Pointer oder in einer anderen festen Rolle).

Dies kann Richard Antwort auf einfachere Art und Weise,

int main() { 
    register int i asm("ebx"); 
    return i + 1; 
} 

obwohl dies eher bedeutungslos ist, da man keine Ahnung hat, was in der ebx Register replizieren.

Wenn Sie diese beiden kombiniert, Kompilieren dies mit gcc -ffixed-ebx,

#include <stdio.h> 
register int counter asm("ebx"); 
void check(int n) { 
    if (!(n % 2 && n % 3 && n % 5)) counter++; 
} 
int main() { 
    int i; 
    counter = 0; 
    for (i = 1; i <= 100; i++) check(i); 
    printf("%d Hamming numbers between 1 and 100\n", counter); 
    return 0; 
} 

können Sie sicherstellen, dass eine C-Variable besteht in einem Register für einen schnellen Zugriff verwendet immer und wird auch nicht von anderen generierten Code clobbered erhalten. (Handlich, ebx ist Rufenen-save unter üblichen x86-Aufrufkonventionen, also auch wenn es durch Gespräche mit anderen Funktionen ohne -ffixed-* zusammengestellt verprügelt wird, soll es auch wieder gehen.)

Auf der anderen Seite, das ist definitiv nicht portable, und ist normalerweise auch kein Leistungsvorteil, da Sie die Freiheit des Compilers einschränken.