byte an Prozedur als Parameter übergeben und dann mit call aufrufen?
-
Hallo,
in MASM32 gibt es ja 2 Möglichkeiten Funktionen aufzurufen - call und invoke. Ich habe eine Prozedur:
EineProzedur proc sFoo:dword, iSize:dword, iNumber:byte
Bevor ich diese mit call aufrufe, muss ich ja die Parameter auf den Stack tun. Bytes kann man aber nicht pushen. Wie kann ich die Parameterübergabe dann korrekt bewerkstelligen?
Mit freundlichen Grüßen,
Developer30
-
Du musst das BYTE in ein DWORD packen. Der Assembler kontrolliert bei der Parameteruebergabe, das der Wert
dieses DWORDs im Bereich 0 - 255 (BYTE) liegt.
-
muss ich immer ein DWORD übergeben? wenn z.B. jetzt ein WORD habe, könnte ich das ja direkt auf den Stack tun.
-
Der push Befehl funktioniert in einem 32 Bit Programm nur mit 32 Bit Werten = DWORD. Also WORD in DWORD packen usw.
Wenn Du 16 Bit Programme schreibst, ist das anders - da kann man nur WORD (16 Bit) mit einem push Befehl auf den Stack legen.
-
NNN schrieb:
Der Assembler kontrolliert bei der Parameteruebergabe, das der Wert
dieses DWORDs im Bereich 0 - 255 (BYTE) liegt.nein, das tut er nicht.
Aber Achtung: ältere MASM-Versionen haben eine ziemlich berühmten Bug im invoke-macro, bei dem für BYTE-Parameter falschen Code erzeugt wird!
Grundsätzlich ist es besser, nur Parametertypen zu nehmen, die ein Vielfaches von 4 sind. Alles andere als pointer oder entsprechend erweitern. (z.B. mit movzx oder movsx)
-
NNN schrieb:
Der push Befehl funktioniert in einem 32 Bit Programm nur mit 32 Bit Werten = DWORD. Also WORD in DWORD packen usw.
Wenn Du 16 Bit Programme schreibst, ist das anders - da kann man nur WORD (16 Bit) mit einem push Befehl auf den Stack legen.hm komisch.
push ax
funktioniert in meinem 32bit Programm ohne error.
masm schrieb:
ältere MASM-Versionen haben eine ziemlich berühmten Bug im invoke-macro, bei dem für BYTE-Parameter falschen Code erzeugt wird!
ich möchte ja call benutzen
-
Developer30 schrieb:
funktioniert in meinem 32bit Programm ohne error.
Sollte es auch, ist aber trotzdem schlecht (performance).
Wenn du WinAPI Funktion aufrufen willst, muss das stack algiment (=N*4) stimmen, da es Funktionen gibt, die bei misalignment ein exception auslösen.
Besser ist z.B.:movzx/movsx eax,... push eax push arg2 push arg1 call Fnc ;add esp,3*4 ; wenn c-call
-
in den meisten Fällen kommt man mit DWORD ja hin. Aber wenn ich wie ganz oben ein BYTE habe, dann kann ich das in ein DWORD reinschreiben und das pushen? Und wird es nachher auch als Parameter wieder richtig eingelesen?
-
Developer30 schrieb:
in den meisten Fällen kommt man mit DWORD ja hin. Aber wenn ich wie ganz oben ein BYTE habe, dann kann ich das in ein DWORD reinschreiben und das pushen? Und wird es nachher auch als Parameter wieder richtig eingelesen?
ja. Die Parametergröße wird entsprechend dem algiment aufgerundet: wenn du ein BYTE deklarierst, werden trotzdem 4 BYTE für den Parameter reserviert – es wird dann halt nur das niederwertigste BYTE im DWORD verwendet.
-
masm schrieb:
es wird dann halt nur das niederwertigste BYTE im DWORD verwendet.
ah ok. danke
-
NNN schrieb:
Der push Befehl funktioniert in einem 32 Bit Programm nur mit 32 Bit Werten = DWORD. Also WORD in DWORD packen usw.
Wenn Du 16 Bit Programme schreibst, ist das anders - da kann man nur WORD (16 Bit) mit einem push Befehl auf den Stack legen.Und wie möchtest du dann mit einem 32 Bit Programm ein "push segreg" machen?
http://www.fermi.mn.it/linux/quarta/x86/push.htm
IF StackAddrSize = 16
THEN
IF OperandSize = 16 THEN
SP := SP - 2;
(SS:SP) := (SOURCE); (* word assignment )
ELSE
SP := SP - 4;
(SS:SP) := (SOURCE); ( dword assignment )
FI;
ELSE ( StackAddrSize = 32 )
IF OperandSize = 16
THEN
ESP := ESP - 2;
(SS:ESP) := (SOURCE); ( word assignment )
ELSE
ESP := ESP - 4;
(SS:ESP) := (SOURCE); ( dword assignment
FI;
FI;Description:
PUSH decrements the stack pointer by 2 if the operand-size attribute of the instruction is 16 bits; otherwise, it decrements the stack pointer by 4. PUSH then places the operand on the new top of stack, which is pointed to by the stack pointer.Hinweis:
Der Unterschied zwischen dem 32Bit-Mode und dem 16 Bit-Mode auf einem Intel 80686+ liegt einzig und alleine in der Bedeutung/Verwendung der Operandsize/Registersize/Adressize-Prefixe.
So ist es auch im 16 Bit-Mode möglich 32 Bit-Register/32 Bit-Adressen(bis zu 4 GiB)/32 Bit-Operationen zu verwenden und im 32 Bit-Mode ist es möglich 16 Bit-Register/16 Bit-Adressen/16 Bit-Operationen zu verwenden.Dirk