Wünsche und Anregungen | | | |  H.Brill | Manchmal reichen die 15 Parameter ja nicht. siehe
aus der Glu32.dll
Wenn es technisch machbar wäre, könnte evtl. ein SET - Befehl, der die Anzahl angibt bzw. aus/einschaltet hilfreich sein :
SET("DLLParameters", x%)
SET("DLLParameters", 0/1)
Wenn oGL schon das Nutzen der API anbietet, sollten auch alle Funktionen nutzbar sein.
Oder weiß jemand, wie man obiger oGL-Funktion noch anders die 19 Parameter übergibt ? |
| | | Benutze XPROFAN X3 + FREEPROFAN Wir sind die XProfaner. Sie werden von uns assimiliert. Widerstand ist zwecklos! Wir werden alle ihre Funktionen und Algorithmen den unseren hinzufügen.
Was die Borg können, können wir schon lange. | 01.08.2023 ▲ |
| |
| |  Jens-Arne Reumschüssel | Wir haben das Thema ausführlich in Paule's PC-Forum diskutiert - herausgekommen ist das hier. Auf diese Weise lassen sich beliebig viele Parameter für einen Funktionsaufruf nutzen. Sie werden Stück für Stück auf den Stack gepusht und dann wird die Funktion aufgerufen, die diese Parameter nutzt.
declare _params&[],_hGluDll&,_gluLookAtFuncAddr& declare eyeX!,eyeY!,eyeZ!,centerX!,centerY!,centerZ!,upX!,upY!,upZ!
ASM "LoopAndCall",3 'hier wird die Parameteranzahl mit übergeben und in einer Schleife abgearbeitet MOV ECX,Par1 // ECX=Count-Register für die Schleife mit der Anzahl Parameter im Array laden, wird bei jedem Loop um 1 verringert (Parameter-Nummer im Array, die Parameter müssen rückwärts auf den Stack gepusht werden [FILO]) // MOV EDX,Par2 // Offset des Array-Speichers in EDX laden - nicht nötig, EDX können wir für etwas anderes aufsparen (z.B. für eine Multiplikation) und stattdessen einfach Par2 benutzen Schleife: MOV EAX,ECX // aktuellen Schleifenzählerstand (=Nummer des aktuellen Paramters im Array) in EAX laden SUB EAX,1 // EAX=ECX-1 (Speicher-Offset im Array ist nullbasiert) ADD EAX,EAX // EAX=EAX+EAX --> im Endeffekt =EAX*2 ADD EAX,EAX // EAX=EAX+EAX --> im Endeffekt zusammen mit der Zeile davor =EAX*4 (das ist das Offset für den Parameter im Array-Speicher) // so ginge die Multiplikation auch: // MOV EDX,4 // MUL EDX // multipliziert den Inhalt des EAX-Registers mit dem Inhalt des EDX-Registers (4) und schreibt das Ergebnis ins EAX-Register zurück ADD EAX,Par2 //,EDX // Offset des Array-Speicherbereichs zu EAX dazuaddieren MOV EBX,EAX // Speicheradresse in EBX schreiben (eigentlich nicht nötig, aber so ist es klarer) MOV EAX,[EBX] // Parameter an der Speicheradresse in EAX laden - es ginge auch MOV EAX,[EAX] (damit würde man EBX für etwas anderes aufsparen und könnte sich die Zeile hiervor sparen) PUSH EAX // Parameter auf den Stack pushen LOOP Schleife // ECX um 1 verringern und zurückspringen, bis 0 erreicht ist CALL Par3 // Funktion aufrufen ENDASM
cls _hGluDll&=@usedll("glu32.dll") _gluLookAtFuncAddr&=@external("kernel32.dll","GetProcAddress",_hGluDll&,"gluLookAt") 'Adresse der aufzurufenden Funktion ermitteln _params&[1]=@long(@addr(eyeX!),0) _params&[2]=@long(@addr(eyeX!),4) _params&[3]=@long(@addr(eyeY!),0) _params&[4]=@long(@addr(eyeY!),4) _params&[5]=@long(@addr(eyeZ!),0) _params&[6]=@long(@addr(eyeZ!),4) _params&[7]=@long(@addr(centerX!),0) _params&[8]=@long(@addr(centerX!),4) _params&[9]=@long(@addr(centerY!),0) _params&[10]=@long(@addr(centerY!),4) _params&[11]=@long(@addr(centerZ!),0) _params&[12]=@long(@addr(centerZ!),4) _params&[13]=@long(@addr(upX!),0) _params&[14]=@long(@addr(upX!),4) _params&[15]=@long(@addr(upY!),0) _params&[16]=@long(@addr(upY!),4) _params&[17]=@long(@addr(upZ!),0) _params&[18]=@long(@addr(upZ!),4) print LoopAndCall(18,@addr(_params&[1]),_gluLookAtFuncAddr&) '1. Parameter: Anzahl Parameter, 2. Parameter: Adresse des Parameter-Arrays, 3. Parameter: Funktionsadresse waitinput freedll _hGluDll& end
Bitte verzeiht mir den Assembler-Code, ich habe noch nie (sic!) irgendetwas Sinnvolles in Assembler zustandebekommen, obwohl ich es oft versucht habe. Aus diesem Grund habe ich das so intensiv und vermutlich sehr laienhaft kommentiert. Wahrscheinlich würde jemand, der sich damit wirklich auskennt, das eleganter machen, aber es funktioniert.
Beste Grüße, Jens-Arne |
| | | XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win10 64bit * PC i7-7700K@4,2GHz, 16 GB Hauptspeicher PM: jreumsc@web.de | 04.08.2023 ▲ |
| |
| |  Jens-Arne Reumschüssel | So, und kann mir jetzt bitte irgendjemand erklären, wie es sein kann, dass gluLookAt in glu32.dll neun *Float*-Werte als Parameter erwartet, die 64 bit breit sind? Jeder 32-bit-Compiler übergibt 32-bit-Werte als Parameter auf den Stack. Wie soll denn sowas ohne unseren mühsamen Workaround-Murks oben bitte gehen? Das kann ich überhaupt nicht begreifen.
Siehe [...] 
Gruß, Jens-Arne |
| | | XProfan X4XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win10 64bit * PC i7-7700K@4,2GHz, 16 GB Hauptspeicher PM: jreumsc@web.de | 04.08.2023 ▲ |
| |
| |  Sven Bader | Auch hier noch mal danke für deine tolle Assembler Funktion!
In der OpenGL DLL ist jede Funktion mehrfach enthalten für 2, manchmal 5 Datentypen. Das sieht das so aus:
glTranslatef() für 32 Bit Float glTranslated() für 64 Bit Float
Die Funktion entspricht dem XProfan ogl("move",x,y,z)
glu scheint dieses Anatz nicht zu verfolgen und nimmt dann im Zweifel eher mal Double, was natürlich im 3D-Kontext nicht falsch ist. |
| | | | |
| |  Jens-Arne Reumschüssel | Ich habe die ASM-Funktion für die verschiedenen Calling-Conventions generalisiert, sodass damit jede erdenkliche 32-bit-DLL bedient werden kann. Außerdem habe ich sie in PushParamsAndCall umbenannt.
declare _params&[],_hGluDll&,_gluLookAtFuncAddr& declare eyeX!,eyeY!,eyeZ!,centerX!,centerY!,centerZ!,upX!,upY!,upZ!
def &stdcall 1 'Parameter absteigend auf den Stack, Funktion bereinigt den Stack def &cdecl 2 'Parameter absteigend auf den Stack, Aufrufer muss den Stack selbst bereinigen def &pascal 3 'Parameter aufsteigend auf den Stack, Funktion bereinigt den Stack
ASM "PushParamsAndCall",4 MOV ECX,Par1 'ECX=Count-Register für die Schleife mit der Anzahl Parameter im Array laden, wird bei jedem Loop um 1 verringert (Parameter-Nummer im Array, die Parameter müssen, außer bei Pascal-Calling-Convention, rückwärts auf den Stack gepusht werden [FILO]) MOV EDX,Par2 'Offset des Array-Speichers in EDX laden (ist schneller als der Zugriff über den Parameter, welcher auch ginge) MOV EAX,Par4 '1=stdcall, 2=cdecl, 3=Pascal CMP EAX,3 JZ PascalSchleife Schleife: MOV EAX,ECX 'aktuellen Schleifenzählerstand (=Nummer des aktuellen Paramters im Array) in EAX laden DEC EAX 'EAX=ECX-1 (Speicher-Offset im Array ist nullbasiert); SUB EAX,1 ginge auch ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt =EAX*2 ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt zusammen mit der Zeile davor =EAX*4 (das ist das Offset für den Parameter im Array-Speicher) ADD EAX,EDX 'Offset des Array-Speicherbereichs zu EAX dazuaddieren MOV EAX,[EAX] 'Parameter an der Speicheradresse in EAX laden PUSH EAX 'Parameter auf den Stack pushen LOOP Schleife 'ECX um 1 verringern und zurückspringen, bis 0 erreicht ist JMP CallFunction PascalSchleife: MOV EAX,Par1 SUB EAX,ECX 'Parameter in aufsteigender Reihenfolge auf den Stack legen (Pascal-Calling-Convention) ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt =EAX*2 ADD EAX,EAX 'EAX=EAX+EAX --> im Endeffekt zusammen mit der Zeile davor =EAX*4 (das ist das Offset für den Parameter im Array-Speicher) ADD EAX,EDX 'Offset des Array-Speicherbereichs zu EAX dazuaddieren MOV EAX,[EAX] 'Parameter an der Speicheradresse in EAX laden PUSH EAX 'Parameter auf den Stack pushen LOOP PascalSchleife 'ECX um 1 verringern und zurückspringen, bis 0 erreicht ist CallFunction: CALL Par3 'Funktion aufrufen; ab hier EAX nicht mehr anfassen, da darin der Rückgabewert steht (oder EAX zwischenzeitlich sichern) MOV EBX,Par4 'jetzt prüfen, ob cdecl, dann muss der Stack manuell bereinigt werden CMP EBX,2 JNZ Ende 'stdcall & Pascal: Stack wurde bereits von der Funktion bereinigt MOV EBX,Par1 ADD EBX,EBX ADD EBX,EBX ADD ESP,EBX 'Stack bereinigen (cdecl) Ende: 'Return-Wert steht in EAX ENDASM
cls _hGluDll&=@usedll("glu32.dll") _gluLookAtFuncAddr&=@external("kernel32.dll","GetProcAddress",_hGluDll&,"gluLookAt") 'Adresse der aufzurufenden Funktion ermitteln _params&[1]=@long(@addr(eyeX!),0) _params&[2]=@long(@addr(eyeX!),4) _params&[3]=@long(@addr(eyeY!),0) _params&[4]=@long(@addr(eyeY!),4) _params&[5]=@long(@addr(eyeZ!),0) _params&[6]=@long(@addr(eyeZ!),4) _params&[7]=@long(@addr(centerX!),0) _params&[8]=@long(@addr(centerX!),4) _params&[9]=@long(@addr(centerY!),0) _params&[10]=@long(@addr(centerY!),4) _params&[11]=@long(@addr(centerZ!),0) _params&[12]=@long(@addr(centerZ!),4) _params&[13]=@long(@addr(upX!),0) _params&[14]=@long(@addr(upX!),4) _params&[15]=@long(@addr(upY!),0) _params&[16]=@long(@addr(upY!),4) _params&[17]=@long(@addr(upZ!),0) _params&[18]=@long(@addr(upZ!),4) print PushParamsAndCall(18,@addr(_params&[1]),_gluLookAtFuncAddr&,&stdcall) '1. Parameter: Anzahl Parameter, 2. Parameter: Adresse des Parameter-Arrays, 3. Parameter: Funktionsadresse, 4. Parameter: Calling-Convention waitinput freedll _hGluDll& end
|
| | | XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win10 64bit * PC i7-7700K@4,2GHz, 16 GB Hauptspeicher PM: jreumsc@web.de | 05.08.2023 ▲ |
| |
|
AntwortenThemenoptionen | 140 Betrachtungen |
ThemeninformationenDieses Thema hat 3 Teilnehmer: |