| |
|
|
- Seite 1 - |
|
Uwe ''Pascal'' Niemeier | Hi Leute!
In der Hoffnung, daß hier der eine oder andere ASM-Kenner mitliest, stelle ich mal 'ne Frage:
Ich suche eine Möglichkeit, eine StdCall-Funktion mit beliebig vielen Parametern aufzurufen. Das das grundsätzlich möglich ist, zeigt dieses Snippet:
Das klappt sowohl als Funktion in einer dll als auch als "Embedded ASM" direkt in Profan:
window 800,600
declare a#:dim a#,48
long a#,0=734366549,1088979908,83395421,79824245
long a#,16=-2095256832,91556088,-352319294,217613074
long a#,32=214041973,-2096567552,58003704,4290
print call(a#,1)
print call(a#,1,2)
print call(a#,1,2,3)
print call(a#,1,2,3,4)
waitinput
Nun denke ich aber, es sollte auch einfacher und universeller gehen, indem man durch verbiegen von Pointern mit einem einfachen RET auskommt und sich den Bandwurm von IF-Abfragen sparen kann (RET akzeptiert ja keine Register als Parameter). Stehe da allerdings etwas auf dem Schlauch, was Stack-Manipulationen betrifft.
Kann jemand helfen?
[OFFTOPIC]BTW: @ iF: Hab's irgendwie nicht hingekriegt, dieses Posting unter "Assembler" abzulegen [/OFFTOPIC]
SeeYou Pascal |
|
|
| |
|
|
|
« Dieser Beitrag wurde als Lösung gekennzeichnet. » |
|
| Hallo Uwe, ist gelungen...
bzw.
bzw.
Ablauf fehlerfrei getestet unter 32Bit WinXP XProfan 11.
Man muss halt die Rücksprungandresse sichern und diese nach künstlichem Reduzieren des Stacks an die neue Stackposition ablegen.
Würde mich freuen wenn Du damit etwas anfangen kannst. |
|
|
| |
|
|
|
|
| Ich glaube ich wüsste schon wie man das ... ich teste das heute Abend gleich mal und berichte. (ohne Ifs, Schleifen und jmp eax*sonstwas)
[OFFTOPIC]Hab den Topic per DB nach Assembler verschoben. Als ich eben probierte hier in unter Assembler Topics zu erzeugen (auch gleichnamige) funktionierte das problemlos. Was genau war passiert das sich das Thema hier nicht ablegen ließ?[/OFFTOPIC] |
|
|
| |
|
|
|
| Hallo Uwe, ist gelungen...
bzw.
bzw.
Ablauf fehlerfrei getestet unter 32Bit WinXP XProfan 11.
Man muss halt die Rücksprungandresse sichern und diese nach künstlichem Reduzieren des Stacks an die neue Stackposition ablegen.
Würde mich freuen wenn Du damit etwas anfangen kannst. |
|
|
| |
|
|
|
Uwe ''Pascal'' Niemeier | Hi iF!
Klasse! Haut hin!
Die Funktion soll immer nur einen konstanten Wert zurückgeben, aber eben bei beliebig vielen Parametern, unabhängig von deren Inhalt.
Ich will daraus eine universelle Dummy-Funktion für OLE-Interfaces basteln (war ja klar ) Leider klappt eben das noch nicht, wahrscheinlich weil gerade da meine Berechnung der Rücksprungadresse/Parameterzahl nicht stimmt. Aber das kriege ich raus...
Danke für deine Hilfe!
PS: Wenn du dies liest hat das Posting geklappt
SeeYou Pascal |
|
|
| |
|
|
|
| Juhu ^^
Stumpf gesagt reichts scheinbar wenn am Funktionkopf steht um den Stack für ret 0 zu präparieren bei egal wie vielen Params. |
|
|
| |
|
|
|
Uwe ''Pascal'' Niemeier | Nachtrag @ iF:
Trotz deiner Lösung werde ich diese Technik wohl nicht verwenden können Anscheinend kann es vorkommen, daß der Aufrufer ( in meinem Fall Windows selbst, das die Methoden meines Interfaces aufruft ) vor dem Funktionsaufruf Werte für den Eigenbedarf auf den Stack pusht, die gar nicht als Parameter für die Funktion vorgesehen sind. Und damit ist die Parameterberechnung durch ebp minus esp hinfällig Also ist es weiterhin nötig, für jede Parameterzahl eine eigene Dummy-Funktion bereitzustellen. Aber den Versuch war's wert!
SeeYou Pascal |
|
|
| |
|
|
|
| Sorry, da habe ich ad hoc auch keine Idee - besonders wenn die Aufruferfunktion auch mit dem Stack werkelt.
Ich könnte mir noch vorstellen das "Win" die Differenz in solch Fall in einem Register mitliefert oder per Stack - da eine Abhängigkeit herauszufummeln ist aber bestimmt ziemlich "irre". |
|
|
| |
|
|
|
| Obwohl...
Wenn Du mal lauter Longs vom Stack einfach frech in einen Debugviewer puschst ...
vlt. klappts ja wenn man mehr als nur 1 Long zurücksichert. |
|
|
| |
|
|
|
Uwe ''Pascal'' Niemeier | Hi iF!
Ich glaube inzwischen nicht mehr, daß das Ganze machbar ist: Jede Methode hat nun mal eine feste Anzahl Parameter, und derjenige, der die Methoden bereitstellt (und darum geht es ja), hat eben dafür Sorge zu tragen, daß diese Parameter korrekt bearbeitet werden. Warum sollte sich M$ die Mühe machen, diese Anzahl irgendwo einzubauen? Und wenn, wäre es eben undokumentiert und damit seeeehr wackelig...Die Idee mit der MultiParameter-Methode ist ja auf meinem Mist gewachsen Außerdem hält sich der Aufwand bei der bisherigen Technik auch in Grenzen; hier eine Version des OLE-RTF-Controls:
window 800,600
$H Windows.ph
$H RichEdit.ph
usermessages 16'--WM_CLOSE
def StgCreateDocfileOnILockBytes(4) !"ole32","StgCreateDocfileOnILockBytes"
def CreateILockBytesOnHGlobal(3) !"ole32","CreateILockBytesOnHGlobal"
def &NI $80004001'--Not Implemented
def &OK 0'----------OK
proc CreateIMD'---------------------------------------InterfaceMethodDummy
var a&=~GlobalAlloc(0,8)
byte a&,0=$B8'-------mov eax,&(2)
long a&,1=&(2)'------Rückgabe: vorgegebene Konstante
byte a&,5=$C2'-------ret &(1)*4+4
word a&,6=&(1)*4+4'--Anzahl Parameter * 4 + "This"-Pointer
return a&'-----------Fertige Funktion im Speicher
'--PS: Mit ein paar NOP's zum Verschieben der Platzhalter paßt alles in 1 Zeile mit 4 LongInts
endproc'------------------------------------------------------------------
proc GetNewStorage'------------------------------------------GetNewStorage
parameters IFace&,IStorage&
declare ILockBytes&
CreateILockBytesOnHGlobal(0,1,addr(ILockBytes&))
StgCreateDocfileOnILockBytes(ILockBytes&,$1012,0,IStorage&)
call(long(long(ILockBytes&,0),8),ILockBytes&)'--ILockBytes::Release
return &OK
endproc'------------------------------------------------------------------
declare VTable#:dim VTable#,60'-----------------------IRichEditOleCallback-Interface
long VTable#, 0=CreateIMD(1,&NI)'-------------QueryInterface
long VTable#, 4=CreateIMD(0,&NI)'-------------AddRef
long VTable#, 8=CreateIMD(0,&NI)'-------------Release
long VTable#,12=procaddr("GetNewStorage",2)'--GetNewStorage
long VTable#,16=CreateIMD(3,&NI)'-------------GetInPlaceContext
long VTable#,20=CreateIMD(1,&NI)'-------------ShowContainerUI
long VTable#,24=CreateIMD(3,&OK)'-------------QueryInsertObject
long VTable#,28=CreateIMD(1,&NI)'-------------DeleteObject
long VTable#,32=CreateIMD(5,&OK)'-------------QueryAcceptData
long VTable#,36=CreateIMD(1,&NI)'-------------ContextSensitiveHelp
long VTable#,40=CreateIMD(3,&NI)'-------------GetClipboardData
long VTable#,44=CreateIMD(3,&NI)'-------------GetDragDropEffect
long VTable#,48=CreateIMD(4,&NI)'-------------GetContextMenu
long VTable#,52=VTable#
var IFace&=VTable#+52
var Edit&=create("richedit",%hwnd,"",20,20,500,500)
sendmessage(Edit&,~EM_SETOLECALLBACK,0,IFace&)'---EM_SETOLECALLBACK
var Datei$=loadfile$("RTF mit Objekten wählen","*.rtf")
Rtf("LoadRTF",Edit&,Datei$)
while 1
waitinput
case %umessage=16:break
endwhile
sendmessage(Edit&,~EM_SETOLECALLBACK,0,0)
destroywindow(Edit&)
dispose VTable#
'--Hier müßten eigendlich alle Methoden-Dummys mit ~GlobalFree() freigegeben werden
War aber gut, mal wieder ein wenig ASM zu üben
SeeYou Pascal |
|
|
| |
|
|