2016-12-13 2 views
0

Ich möchte ein Makro erstellen, die ein qword (dezimal) drucken.Drucken Sie ein in eax gespeichertes Wort: ebx x86

show_qd macro nr 
    lea edx,[nr] 
    mov eax,[edx] ;upper 32 bits 
    mov ebx,[edx+4] ;lower 32 bits 

    ;print code here; 

endm 

Leider kann ich nicht herausfinden, wie es mit x86-Befehlen zu tun ...

+2

Ausdrucken - wie? Dezimal, hexadezimal, binär? Können Sie herausfinden, wie Sie einen einzelnen Byte-Wert in dem Notationssystem Ihrer Wahl drucken können? – usr2564301

+1

Wenn dezimal, können Sie hier nach einer Routine suchen: http://StackOverflow.com/a/41086442/4271923 (übrigens, setzen Sie nicht ganze Routine in Makro, wird es im Maschinencode für jede Verwendung = = wiederholen große binäre => langsam. Verwenden Sie lieber 'call' und Unterprogramme.) – Ped7g

+1

Ich fand einen sehr einfachen Weg: push ebx; untere 32 Bits push eax; obere 32 Bits Push-Offset-Format Aufruf printf add esp, 12; Löschen Sie den Stapel wo Format ist Format DB "% lld", 0 – Crisan

Antwort

0

Es gibt keinen x86-Befehl zu „drucken“ ein Wert. Die Anzeige der Ausgabe erfordert eine betriebssystemspezifische Schnittstelle. Bei der "klassischen" x86-Programmierung würden Sie einen BIOS-Aufruf durchführen, um die Ausgabe auf dem Bildschirm zu generieren. In modernen Protected-Mode-Betriebssystemen wird dies nicht mehr funktionieren. Stattdessen müssen Sie eine OS-API-Funktion aufrufen, um die Ausgabe anzuzeigen, z. B. . an ein Konsolenfenster, das mit Ihrem Prozess verknüpft ist.

Die einfachste und universellste Methode zum Aufrufen dieser OS-API besteht darin, das Assembly-Programm mit der C-Standardbibliothek zu verknüpfen, sodass Sie die printf (und ähnliche) Funktion (en) aufrufen können. Dies erfordert wenig mehr als eine CALL-Anweisung, die die Steuerung an die printf-Funktion überträgt, sie ausführt und die Steuerung an die folgende Anweisung in Ihrem Code zurückgibt.

Es gibt jedoch noch eine zusätzliche Komplikation: Sie müssen die entsprechende Aufrufkonvention für Ihre Plattform und für die Standardbibliotheksfunktionen befolgen. Ihre Frage bietet keine Hinweise darauf, ob Sie Windows, Linux oder etwas anderes verwenden. Glücklicherweise sind detaillierte Informationen über x86-Aufrufkonventionen im -Tag-Wiki verfügbar, erreichbar unter here. Im Allgemeinen übergeben 32-Bit-Aufrufkonventionen Parameter auf dem Stapel von rechts nach links. Und die C-Standardbibliotheksfunktionen sind praktisch immer aufruferbereinigend (selbst unter Windows, wo sonst eine Aufräumkonvention üblich ist), so dass Sie nach dem Aufruf dafür verantwortlich sind, den Stapel zu bereinigen.

So, wie eine Demonstration hier ist, wie Sie printf nennen könnten die 32-Bit-Integer im EAX Register gespeichert drucken:

push eax     ; push 32-bit integer value from EAX onto stack 
push OFFSET strFormat  ; push pointer to format string onto stack 
call printf 
add esp, 8    ; clean up stack 

strFormat muß in Ihrem ausführbaren DATA Abschnitt gespeichert ein String sein. Die Formatzeichenfolgen sind die gleichen wie für C, da es genau die gleiche Funktion ist. In diesem Fall würde dann ein Zeiger auf eine Zeichenfolge mit "%d" gesetzt werden.

Die Dinge sind sehr ähnlich, um einen 64-Bit-Wert zu drucken, außer dass Ihre Formatzeichenfolge "%lld" ist (verwenden Sie den long long-Typ in C, der 64 Bit auf x86-32 ist). Sie müssen den Regeln der Aufrufkonvention folgen, um einen 64-Bit-Integer-Parameter an eine Funktion zu übergeben. Es ist wahrscheinlich, dass dies einfach dazu führt, beide 32-Bit-Hälften auf den Stapel zu schieben. Unter der Annahme, dass der 64-Bit-Wert kanonisch in EDX:EAX gespeichert wird, würde der Code wie folgt aussehen:

push edx     ; push upper 32 bits of 64-bit integer value onto stack 
push eax     ; push lower 32 bits of 64-bit integer value onto stack 
push OFFSET strFormat64  ; push pointer to format string onto stack 
call printf 
add esp, 12    ; clean up stack 

Wenn der Wert im Speicher vorhanden ist, dann können Sie Code verwenden, wie Sie in der Frage zeigen:

lea edx, DWORD PTR [value] 
mov eax, DWORD PTR [edx] 
mov edx, DWORD PTR [edx+4] 

push edx 
push eax 
push OFFSET strFormat64 
call printf 

add esp, 12 

Beachten Sie, dass wenn Sie dies als ein Makro implementieren, es Clobber-Register wird. Stellen Sie sicher, dass dies entweder eindeutig dokumentiert ist oder dass Sie die Register innerhalb des Makros speichern und wiederherstellen. Andernfalls werden Sie mit schwer zu debuggenden Problemen konfrontiert, wenn Sie dies in Ihrem Code verwenden! Abhängig von Ihrer Aufrufkonvention müssen Sie möglicherweise sicherstellen, dass der Stapel korrekt ausgerichtet ist. Dies kann in einem Makro schwierig und generisch schwierig sein. MASM verfügt über eine INVOKE Pseudo-Anweisung, die automatisch eine Funktion für Sie aufrufen kann.Es könnte sich lohnen zu überprüfen, ob Ihr Assembler eine ähnliche Funktion hat.

Verwandte Themen