2010-09-14 6 views
9

Der folgende Code zeigt nur eine Message-Box auf dem Bildschirm.
Die Adressen werden erleichtern fest einprogrammiert:Definieren von Bytes in GCC Inline-Assembly in Dev-C++ (. ASCII in AT & T-Syntax unter Windows)

int main() 
{ 
    asm("xorl %eax, %eax  \n" 
     "xorl %ebx, %ebx  \n" 
     "xorl %ecx, %ecx  \n" 
     "xorl %edx, %edx  \n" 
     "pushl %ecx    \n" //$0x0 
     "pushl $0x20206c6c  \n" //" ll" 
     "pushl $0x642e3233  \n" //"d.23" 
     "pushl $0x72657375  \n" //"resu" 
     "movl %esp, %ecx  \n" //store "user32.dll" address in %ecx 
     "movl $0x7c801d7b, %ebx \n" //store address of LoadLibraryA in %ebx 
     "pushl %ecx    \n" 
     "call *%ebx    \n" 
     "movl $0xef30675e, %ecx \n" 
     "addl $0x11111111, %ecx \n" 
     "pushl %ecx    \n" 
     "pushl $0x42656761  \n" 
     "pushl $0x7373654d  \n" 
     "movl %esp, %ecx  \n" 
     "pushl %ecx    \n" 
     "pushl %eax    \n" 
     "movl $0x7c80ae40, %ebx \n" 
     "call *%ebx    \n" 
     "movl %esp, %ecx  \n" 
     "xorl %edx, %edx  \n" 
     "pushl %edx    \n" 
     "pushl %ecx    \n" 
     "pushl %ecx    \n" 
     "pushl %edx    \n" 
     "call *%eax    \n" 
     "xorl %eax, %eax  \n" 
     "pushl %eax    \n" 
     "movl $0x7c81cb12, %eax \n" 
     "call *%eax    \n" 
    ); 
} 

(ich den Code nicht alle haben kommentieren, weil meine Frage nicht wirklich über den Code ist)

Meine Frage ist: Gibt es eine Möglichkeit das schreiben Zeichenfolge "user32.dll" in Assembly inline, ohne manuell auf den Stapel zu drücken? Ich meine, wie dies in NASM: db 'Hello'

Ich weiß, dass in AT & T Syntax I .ascii 'Hello' oder .string 'Hello' aber wie wäre es in gcc inline tun könnte?

Bitte beachten Sie, dass ich Dev-C++ auf Windows XP SP3

Dank bin mit!

Antwort

9

Ja, indem Sie Assembler-Anweisungen in Ihrem Inline-Assembler verwenden. Der Trick besteht darin, die Zeichenfolge an die richtige Stelle zu setzen (die Datensektion), was Sie tun können, indem Sie mit .section .data wechseln und dann wieder mit .section .text zurückschalten.

Sie müssen den Daten ein Etikett geben, damit Sie darauf verweisen können; Ich würde empfehlen, die lokale Label-Syntax hier zu verwenden (wo das Etikett eine Nummer ist, zB 1:, und Sie verweisen es entweder 1b für das erste 1: Label rückwärts, oder 1f für das erste 1: Label nach vorne - siehe die GNU assembler documentation für weitere Details) .

So:

int main(void) 
{ 
    asm(".section .data  \n" 
     "1: .asciz \"Hello\" \n" 
     ".section .text  \n" 
     "pushl $1b   \n" 
     "call _puts   \n" 
     "add $4, %esp  \n" 
    ); 
    return 0; 
} 

Ich habe nicht ein Windows-System praktisch diese auf testen, aber es kompiliert OK und sieht aus wie es soll, das Richtige mit Hilfe eines MinGW Cross-Compiler auf Linux tun (Ich glaube Dev-C++ basiert auf MinGW).

Hinweis: Diese Technik ist allgemein anwendbar, wenn Sie eine GNU-Toolchain verwenden. Wenn Sie ELF-Binärdateien (z. B. natives Linux) erstellen, gibt es eine bessere Möglichkeit, zurück zu dem Textabschnitt zu wechseln, der .previous verwenden soll, was bedeutet "was auch immer der Abschnitt vor dem vorherigen .section war". (Das obige Beispiel funktioniert unter Linux, wenn Sie _puts in puts ändern, um verschiedene Vorzeichenkonventionen für Symbole zu berücksichtigen.)

+0

Cool! Bedeutet "1:", dass es sich um eine Bezeichnung für die Adresse der Zeichenfolge handelt? Ist die Anweisung "pushl $ 1b" die Adresse von "Hello"? Was ".previous" tun? Vielen Dank! – jyz

+0

": Funktioniert" .previous "unter Windows? Ich kann nicht .. Ich benutze Dev-Cpp Portable – jyz

+1

@jyzuz: Nein, es scheint nicht; Entschuldigung, dass. Ich habe meine Antwort mit einem aktualisiert Übrigens: '1:' ist in der Tat ein Label, und '1b' bezieht sich darauf (siehe die Assembler-Dokumentation, auf die ich in meiner aktualisierten Antwort verlinkte); also drückt' push $ 1b' den Wert des Labels - was ist die Adresse des Strings - als Konstante auf den Stack. –