1Byte von Stack in Speicher holen
-
Hi,
im Programmcode schiebe ich eine 1 Byte große Konstante auf den Stack mit "push 128" (wobei die 128 ein Beispiel ist).
Anschließend möchte ich diese mittels pop in eine globale Variable holen, diese ist so deklariert:static unsigned char index;
Wenn ich jedoch in VC++ folgendes schreibe: __asm pop [index] erhalte ich folgende Warnung illegal instruction size
Gibt es keinen solchen pop Befehl? Kann ich mir nicht vorstellen, denn wenn ich eine 1 Byte Konstante pushen kann muss ich sie doch auf popen können, oder nicht?
Übrigens erzeugt __asm push [index] die gleiche Warnung, aber wie gesagt __asm push 128 funktioniert ohne Warnung
-
laut meiner assembler referenz kannst du nur minimal 16bit werte vom stack poppen.
Die frage ist aber, warum machst du das in einem c preogramm?
Assembler lohnt sich wirklich nur an wenigen stellen, und das auch nur, wenn man wirklich ahnung von assembler hat.
Moderne Compiler sind recht gut, was Codeoptimierung angeht.Auch ist es in der regel
Wenn ich jedoch in VC++ folgendes schreibe: __asm pop [index] erhalte ich folgende Warnung illegal instruction size
Ich vermute mal, dass liegt daran, dass index ein 8bit wert ist, den du als pointer benutzt.
Das kann eigendlich nur schiefgehen. In c gesprochen heist
pop [index] soviel wie
*index = oberster wert vom stackDu versuchst also an die Speicher Adresse, die in index steht (0-255) ein wert zu schreiben,
Adressen sind normalerweise 32bit breit du addressierst hier den speicher mit 8bitWas versuchst du denn konkret zu erreichen?
möchtest du an die Stelle index eines Arrays daten kopieren, oder auslesen;
oder möchtest du einen index für ein array vom stack holen, oder schreiben.Tip:
lad dir mal masm32 runter, da is ne recht gute assembler befehlsliste dabei (ordner help/opcodes.hlp)
sowie weitere tuts und examples
http://www.masm32.com/
-
Hi, diese eckige Klammersyntax ist für den inline Assembler vom VC da, damit er weiß, dass es sich dabei um eine Variable handelt.
Ok, das mit den 16Bit erklärt einiges, aber dann muss ich ja auch 16Bit pushen, dann hätte ich wieder ein Byte mehr.
Ich möchte einen Speicherbereich einer Anwendung überschreiben, an die Stelle wo ich überschreibe soll zuerst mit push ein index auf den Stack geschoben werden, so dass ich weiß was getan werden soll, danach wird eine generische Funktion aufgerufen die anhand des Index dann die richtige Funktion aufruft.
Wenn ich diese generische Funktion weglasse bräuchte ich den Index nicht, aber dann müsste ich den Assembler Code in der generischen Funktion (zur Sicherung der Register und der Rücksprungadresse) jedes mal aufs Neue schreiben damit ich das nicht muss wollte ich eigentlich diese Funktion schreiben.
Im Moment bin ich bei 7Byte die ich überschreiben muss, wenn ich ein 16Bit push durchführe, dann wären es schon 8Byte, gegenüber 5Byte wenn ich die generische Funktion weglasse. Das Problem ist ja, dass ich erst einmal eine 7 bzw. 8 Byte große Stelle finden muss die ich relativ gefahrlos überschreiben kann.
-
Die minimale Datengroesse, mit der du auf dem Stack operieren kannst, sind 16Bit (push, sowie pop).
Ich nehme stark an, dass masm einen 32Bit-push mit der 128 gemacht hat (AFAIR gibt dafuer eine 2Byte-Kurzform).
BTW: Da du evtl. fuer Windows programmierst: Pass bloss auf, dass der Stack immer dword-aligned bleibt. Alles andere mag Windows in seinen Funktionen naemlich gar nicht.
-
Nobuo T schrieb:
Die minimale Datengroesse, mit der du auf dem Stack operieren kannst, sind 16Bit (push, sowie pop).
Ich nehme stark an, dass masm einen 32Bit-push mit der 128 gemacht hat (AFAIR gibt dafuer eine 2Byte-Kurzform).
BTW: Da du evtl. fuer Windows programmierst: Pass bloss auf, dass der Stack immer dword-aligned bleibt. Alles andere mag Windows in seinen Funktionen naemlich gar nicht.Danke für den Hinweis. Mir fällt durch dein Posting auf, dass ich angenommen habe, dass ein 1Byte push durchgeführt wurde, da der Befehl in OllyDBG scheinbar 2Byte belegt (1Byte wohl das Push, 1Byte die Konstante), und hatte angenommen, dass die CPU auch nur 1Byte Stackspeicher belegt.
Aber dann belegt die CPU wohl sicher 2Byte, dann passt der Rest ja auch, richtig?
-
ASM Noob schrieb:
Aber dann belegt die CPU wohl sicher 2Byte, dann passt der Rest ja auch, richtig?
Nein, die 128 wird aller Wahrscheinlichkeit nach auf 32Bit (4Byte) erweitert. Schau es dir im OllyDbg nochmal an!
-
Nobuo T schrieb:
ASM Noob schrieb:
Aber dann belegt die CPU wohl sicher 2Byte, dann passt der Rest ja auch, richtig?
Nein, die 128 wird aller Wahrscheinlichkeit nach auf 32Bit (4Byte) erweitert. Schau es dir im OllyDbg nochmal an!
Ok, werde ich machen, aber nicht mehr heute Abend.
Im Prinzip ist es ja egal wie viele Bytes er auf dem Stack speichert, ich weiß ja dass ich mit dem push nur 1Byte "echten" Speicher belege und kann ja die übrigen Bytes verwerfen. Von daher hat sich dieser Thread erledigt, insofern ich herausfinde wie viele Bytes dieser push Befehl auf dem Stack speichert.
-
quelle: masm opcode.hlp
PUSH - Push Word onto Stack Usage: PUSH src PUSH immed (80188+ only) Modifies flags: None Decrements SP by the size of the operand (two or four, byte values are sign extended) and transfers one word from source to the stack top (SS:SP). Clocks Size Operands 808x 286 386 486 Bytes reg16 11/15 3 2 1 1 reg32 - - 2 1 1 mem16 16+EA 5 5 4 2-4 (W88=24+EA) mem32 - - 5 4 2-4 segreg 10/14 3 2 3 1 immed - 3 2 1 2-3 FF /6 PUSH r/m16 Push r/m16 FF /6 PUSH r/m32 Push r/m32 50+ rw PUSH r16 Push r16 50+ rd PUSH r32 Push r32 6A PUSH imm8 Push imm8 68 PUSH imm16 Push imm16 68 PUSH imm32 Push imm32 0E PUSH CS Push CS 16 PUSH SS Push SS 1E PUSH DS Push DS 06 PUSH ES Push ES 0F A0 PUSH FS Push FS 0F A8 PUSH GS Push GS
laut den opcodes unten kannst du sowohl 8bit, als auch 16bit, als auch 32bi immediate werte pushen.
Ich vermute aber mal, dass man dann was dazuschreiben muss, woraus der assembler ableiten kann dass er nicht eine 32bit konstante pushen soll, standardmäßig wird er wohl 32bit auf dem stack legen.speicher verbrauchst du natürlich 4byte, auch wenn du weißt, dass da nur 1 Nutzbyte drinsteht.
Auf jeden Fall müssen acuh alle 4 Byte wieder abgeräumt werden, dass du den stack so hinterlässt, wie du ihn vorgefunden hast.Hi, diese eckige Klammersyntax ist für den inline Assembler vom VC da, damit er weiß, dass es sich dabei um eine Variable handelt.
Ich bin mir ziemlich sicher, dass die klammern falsch sind, es sei denn index ist ein pointer.
Die klammern sind in asm immer eine dereferenzierung, dh der wert wird von der speicherstelle geholt auf die der operand zeigt.
wenn du im inline assembler eine Variable benutzt, schreibst du einfach ihren namen
-
Danke für die Tabelle. Diesen "6A" push verwende ich momentan auch (den Patch muss ich ja in Hex codiert speichern und an die richtige Speicherstelle schreiben, daher kann ich mir da siche sein die richtige Instruktion erwischt zu haben).
Aber wie viel Speicher belegt die "6A" Instruktion denn jetzt auf dem Stack? 16Bit? 32Bit?Also wegen der Inline-Syntax bin ich mir nicht zu 100% sicher, habe das auch nur kürzlich wo gelesen, aber die Warnung tritt mit und ohne auf das hat keine Auswirkung.
-
beim PUSH immx wird der Operand immer vorzeichenbehaftet erweitert auf die richtige Größe (in Abhängigkeit des Operandengrößenattributs des gegenwärtgen Codesegments - als 2,4,8 byte bei 16-,32-,64-bit Code).
Der einzige Weg, durch push/pop einen nicht ausgerichteten Stackpointer zu erhalten, ist im 32- bzw. 64-bit-Modus die Verwendung von 16-bit Register- oder Speicher-push/-pop (32-bit kann im 64-bit-Modus nicht encodiert werden). Das ist aber ine schlechte Idee. Zu Prüfen ist sowieso immer, ob nicht einfache mov, gefolgt von einem einzelnen Stackinkrement zu besserem Code führt.
-
Ok, danke.
Da der "6A" push, aber tatsächlich nur ein Byte benötigt macht ihn für meinen Zweck ideal, wie groß das pop ist, ist egal, da die Funktion welche den Wert mit pop vom Stack nimmt ja außerhalb des ursprünglichen Programmcodes steht und daher auch ruhig größer sein kann.
D.h. in meinem Fall (32Bit) führt ein push/pop immer zu einem 4Byte inkrement/decrement des Stack-Pointers?
-
Ok, also ich habe es in OllyDBG überprüft und push/pop schreiben/lesen immer in 4Byte Schritten.
Dann hat sich der Thread hier erledigt, danke für die Hilfe