|
You last visited: Today at 04:23
Advertisement
Problem mit der Parameterübergabe für Inline-ASM in Interpreter-Sprache
Discussion on Problem mit der Parameterübergabe für Inline-ASM in Interpreter-Sprache within the C/C++ forum part of the Coders Den category.
08/18/2015, 21:51
|
#1
|
elite*gold: 77
Join Date: May 2008
Posts: 5,430
Received Thanks: 5,878
|
Problem mit der Parameterübergabe für Inline-ASM in Interpreter-Sprache
Ich bin momentan dabei Inline-Assembler in meinen Interpreter zu integrieren.
Wichtig dabei ist, dass ich den ASM-Code möglichst nur einmalig und möglichst vor dem "Kompilieren" in Opcodes übersetzen möchte.
Bei ASM-JIT-Kompilierung gäbe es mein beschriebenes Problem gar nicht. Aber JIT soll wirklich der letzte Ausweg sein. Ein Notfallplan sozusagen.
Meine Ursprungsidee war einfach und sollte prinzipiell auch klappen.
Sobald mein Interpreter die Stelle des Opcodes erreicht schreibt er ihn in einen Bereich der ausführbar ist und springt ihn an, anschließend wird zurückgesprungen.
Ein Problem gibt es jetzt nur wenn ich mit dem Code-Stück kommunizieren möchte.
Meine Anfangsidee war "einfach" die Werte auf den Stack zu pushen, die ich verwenden möchte und im ASM-Code muss ich sie dann nur poppen.
Pseudocode mäßig also so:
PHP Code:
ByteArray var = #CompileASM("Pop edx \n Pop ecx \n add edx,ecx")
int var2=10
int var3=20
Push(var2)
Push(var3)
Execute(var)
Das Problem dabei ist, dass mein Interpreter ja erst Push interpretieren muss, weswegen ich nicht weiß ob der Stack bis zum Execute nicht schon wieder zugemüllt ist.
Eine Idee, die ich dann hatte war einen extra Speicherbereich zu allokieren für meinen eigenen Stack.
Also in etwa so:
PHP Code:
ByteArray var = #CompileASM("Pop edx \n Pop ecx \n add edx,ecx")
int var2=10
int var3=20
int adresse = VirtualAlloc(...)
int alteAdresse
asm
{
mov alteAdresse, esp
mov esp, adresse
}
Push(var2)
Push(var3)
asm
{
mov esp, alteAdresse
}
asm
{
mov esp, adresse
}
Execute(var)
Aber hier liegt das Problem jetzt, dass ich nicht weiß ob mein Interpreter beim Interpretieren vom "Push" Werte von meinem alten Stack braucht.
Da ich vollen Zugriff auf den zu generierenden ASM-Code habe kann ich auch automatisiert beliebig ASM-Code einfügen lassen falls nötig.
Momentan benutze ich zum Compilen während dem "Compilen von meinem Skriptcode" FASM, um den ASM-Code in den entsprechenden Opcode umzuwandeln.
Wie gesagt würde ich das Ganze JIT machen, könnte ich einfach den Pointer zu den Variablen reinschreiben lassen in den ASM-Code und dann compilen, aber JIT will ich halt eigentlich nicht.
Hat jemand noch eine andere Idee wie ich trotzdem eine Art Parameterübergabe machen kann?
|
|
|
08/19/2015, 07:15
|
#2
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
mach aus der execute funktion eine mit variablen parametern - da pushst du einfach direkt inline die parameter bevor du var aufrufst - dann kannste sicher sein, dass der stack net zwischendurch kaputtgemacht wurde.
alternativ kannst du der execute funktion einen optionalen stackparameter angeben, also quasi:
Code:
MyStack = new Stack_t();
MyStack.push(MyArg3);
MyStack.push(MyArg2);
MyStack.push(MyArg1);
exectue(var, MyStack);
und in execute dann:
Code:
push esp;
mov esp, MyStack.getPtr();
call var;
pop esp;
|
|
|
08/19/2015, 13:17
|
#3
|
elite*gold: 77
Join Date: May 2008
Posts: 5,430
Received Thanks: 5,878
|
Quote:
Originally Posted by Dr. Coxxy
mach aus der execute funktion eine mit variablen parametern - da pushst du einfach direkt inline die parameter bevor du var aufrufst - dann kannste sicher sein, dass der stack net zwischendurch kaputtgemacht wurde.
alternativ kannst du der execute funktion einen optionalen stackparameter angeben, also quasi:
Code:
MyStack = new Stack_t();
MyStack.push(MyArg3);
MyStack.push(MyArg2);
MyStack.push(MyArg1);
exectue(var, MyStack);
und in execute dann:
Code:
push esp;
mov esp, MyStack.getPtr();
call var;
pop esp;
|
Oh das ist eine super Idee, vor allem Variante 2 gefällt mir sehr gut, weil ich damit gleichzeitig gewissermaßen garantieren kann, dass der ASM-Code nicht meinen Interpreter-Stack kaputt machen kann.
Danke dir ich glaube so werde ich es machen.
|
|
|
08/19/2015, 18:11
|
#4
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
Quote:
Originally Posted by Shadow992
Oh das ist eine super Idee, vor allem Variante 2 gefällt mir sehr gut, weil ich damit gleichzeitig gewissermaßen garantieren kann, dass der ASM-Code nicht meinen Interpreter-Stack kaputt machen kann.
Danke dir ich glaube so werde ich es machen. 
|
biddö, pass auf, dass dein manueller stack genug platz für rücksprungadresse, lokale variablen der funktion, etc. hat
|
|
|
08/19/2015, 20:38
|
#5
|
elite*gold: 77
Join Date: May 2008
Posts: 5,430
Received Thanks: 5,878
|
Quote:
Originally Posted by Dr. Coxxy
biddö, pass auf, dass dein manueller stack genug platz für rücksprungadresse, lokale variablen der funktion, etc. hat 
|
Ich werde meinen Stack so implementieren, dass der Skripter angeben muss wie groß der Stack sein soll, wobei ich eine Mindestgröße von 8kb festlegen werde (sollte denke ich für die meisten kleinen Code-Stücke reichen).
Noch eine kleine "Styling"-Frage, mein momentaner Ansatz sieht in etwa so aus:
PHP Code:
Beispielcode: ByteArray var = #CompileASM("Pop edx \n Pop ecx \n add edx,ecx")
MyStack = new Stack(8000); MyStack.push(MyArg2); MyStack.push(MyArg1);
exectue(var, MyStack);
Stack.push-Methode(arg): MyStack.Last_Address+=4 // Die ersten 4 Bytes werden absichtlich leer gelassen mov [MyStack.Last_Address], arg
execute-Methode(opcode,MyStack): mov [MyStack.Start_adress], esp // An der ersten Position von meinem Stack steht immer der original esp-Wert mov esp, MyStack.Last_Adress // neuen esp Wert setzen call opcode mov esp, [MyStack.Start_adress] //Wert zurücksetzen
Sollte ich vor dem Execute Aufruf die General-Purpose-Register sichern oder sollte ich das dem Programmierer des ASM-Codes überlassen?
Für das automatische Sichern spricht, dass es nicht sehr fehleranfällig ist, weil es eben automatisch passiert.
Auf der anderen Seite, wenn jemand nur eax benutzt, "verschwende" ich einige Zyklen mit dem sichern der anderen Register.
Und da man Inline-ASM wohl nur für sehr zeitkritische Sachen benutzt (oder für Sachen, die anders nur schwer umsetzbar sind, da braucht man dann aber meistens auch wenig Register), wäre ein unnötiges Sichern nicht so optimal.
Und wo ich weiterhin sehr "skeptisch" bin ist beim Sichern der Statusregister. Theoretisch sollte der Compiler meiner Meinung nach niemals so viel Code wegoptimieren, dass er ein cmp/add/etc. vom jeweiligen jne/je/etc. "wegzieht" oder lehne ich mich da zu weit aus dem Fenster? Und sollte daher auch die Statusregister sichern (ist das überhaupt möglich)?
|
|
|
08/19/2015, 22:15
|
#6
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
Quote:
Originally Posted by Shadow992
Sollte ich vor dem Execute Aufruf die General-Purpose-Register sichern oder sollte ich das dem Programmierer des ASM-Codes überlassen?
Für das automatische Sichern spricht, dass es nicht sehr fehleranfällig ist, weil es eben automatisch passiert.
Auf der anderen Seite, wenn jemand nur eax benutzt, "verschwende" ich einige Zyklen mit dem sichern der anderen Register.
Und da man Inline-ASM wohl nur für sehr zeitkritische Sachen benutzt (oder für Sachen, die anders nur schwer umsetzbar sind, da braucht man dann aber meistens auch wenig Register), wäre ein unnötiges Sichern nicht so optimal.
|
fasst es eigtl schon gut zusammen, geschmackssache, im zweifel wird bei ner scriptsprache aber perfomance wahrscheinlich eh nicht sooooo ne riesenrolle spielen.
Quote:
|
Und wo ich weiterhin sehr "skeptisch" bin ist beim Sichern der Statusregister. Theoretisch sollte der Compiler meiner Meinung nach niemals so viel Code wegoptimieren, dass er ein cmp/add/etc. vom jeweiligen jne/je/etc. "wegzieht" oder lehne ich mich da zu weit aus dem Fenster? Und sollte daher auch die Statusregister sichern (ist das überhaupt möglich)?
|
O.o wo soll denn der compiler in deinem asm was optimieren?
compiler (zmdst der ms vcc) optimiert kein inline asm.
|
|
|
08/20/2015, 02:47
|
#7
|
elite*gold: 77
Join Date: May 2008
Posts: 5,430
Received Thanks: 5,878
|
Quote:
Originally Posted by Dr. Coxxy
fasst es eigtl schon gut zusammen, geschmackssache, im zweifel wird bei ner scriptsprache aber perfomance wahrscheinlich eh nicht sooooo ne riesenrolle spielen.
|
Alles klar, denke dann auch dass ich die "alles sichern"-Methode nehmenw erde.
Quote:
Originally Posted by Dr. Coxxy
O.o wo soll denn der compiler in deinem asm was optimieren?
compiler (zmdst der ms vcc) optimiert kein inline asm.
|
Naja gehen wir von etwas derartigen in Pseudo-C aus:
PHP Code:
InterpretOpcode(...) if(i==0) { i++; }
Dann wird der Compiler es in etwa in das übersetzen:
PHP Code:
push ... call InterpretOpcode cmp eax, 0 jne end_if inc eax end_if:
Wenn der Compiler aber (aus welchem Optimierungsgründen auch immer), das in folgenden Code umwandeln würde:
PHP Code:
cmp eax, 0 push ... call InterpretOpcode jne end_if inc eax end_if:
Müsste ich das Statusregister ebenfalls sichern, weil es ja sein kann, dass der Aufruf das Register verändert.
Was ich jetzt aussagen wollte ist, dass ich bezweifle, dass die zweite (optimierte) Variante jemals so oder so ähnlich in der "freien" Natur vorkommt. 
Oder liege ich da falsch?
|
|
|
08/20/2015, 10:29
|
#8
|
elite*gold: 966
Join Date: Apr 2010
Posts: 1,105
Received Thanks: 681
|
Das Flag-Register wird in den Konventionen, an denen sich viele Compiler (MSVC eingeschlossen) als "Caller-Saved" angesehen, da sehr viele Instructions Einfluss auf das Flag-Register nehmen. Das heißt, dass angenommen werden muss, dass eine aufgerufene Funktion dieses Register verändert. Braucht man es nach einem call noch, muss man es davor sichern und danch wiederherstellen. Hab noch nie gesehen, dass der Compiler sowas generiert.
Auch einige Register gelten als Caller-Saved. Die muss eine aufgerufene Funktion also nicht sichern. Andere Register gelten als Callee-Saved. Diese müssen am Ende einer Funktion den gleichen Wert wie am Anfang aufweisen.
Welches Register nun was ist, kann  nachgesehen werden.
Mit freundlichen Grüßen
Jeoni
|
|
|
08/20/2015, 18:40
|
#9
|
elite*gold: 0
Join Date: Feb 2011
Posts: 1,206
Received Thanks: 736
|
falls du wirklich funktionsübergreifend einen gleichen kontext in deiner scriptsprache anbieten willst, sollteste dir mal angucken wie windows die threads und deren kontexte verwaltet, stichwort get/setthreadkontext und der kontext struktur angucken (findeste in der winnt.h) sowie mal bissle guglen oder windows internals lesen - da kannste dir evtl. bissle abgucken.
EDIT:
achsoo, jetzt erst dein problem verstanden - nein, solange du dich an die von jeon erwähnten regeln innerhalb deines assemblers hältst, bzw. durch speichern der entsprechenden register vor ausführen des scriptcodes sicherstellst, dass diese beachtet werden, kriegst du keine probleme.
|
|
|
 |
Similar Threads
|
PHP Parameterübergabe safe_xss($_GET['variable'])
04/11/2015 - Web Development - 8 Replies
danke an alle die geholfen haben :)
|
[Problem] Embedding Boost.Python as an interpreter
06/11/2014 - C/C++ - 1 Replies
Hi there :)
Im trying around with boost.python because i want to embed a pythoninterpreter to a program.
I already searched for good examples that show the usage but everything i find isnt very informative or just doesnt really work.
Running a simple script doesnt even work :(.
int main (void)
{
Py_Initialize();
|
Problem - Inline Assembly Call Function
05/24/2014 - C/C++ - 9 Replies
Old Client Function:
00414710 - push ecx
00414711 - mov ecx,
00414715 - lea eax,
00414718 - push eax
00414719 - push 00
0041471B - push ecx
0041471C - call 00520550
00414721 - add esp,0C
|
[Problem] ELF interpreter /libexec/ld-elf.so.d not found
04/11/2012 - Metin2 Private Server - 3 Replies
Fehler meldung
ist
ELF interpreter /libexec/ld-elf.so.d not found
Real Server
Log Offmysql_real_connect: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
failed, retrying in 5 secondsAbort trap
ELF interpreter /libexec/ld-elf.so.d not found
|
[Java]Probleme bei Parameterübergabe!
08/12/2010 - General Coding - 1 Replies
||==German Version==||
Hallo Leute!
Ich versuche für Nostale gerade nen kleinen Bot selber zu schreiben hab aber so meine kleinen Probleme damit.
Also meine alles-leitende-Methode run() erhält 10 Parameter von der GUI-klasse.
Diese 10 Parameter gebe ich dann an eine andere Methode weiter aber ständig komm folgende Fehlermeldung:
Compiliere C:\Dokumente und Einstellungen\Dragono\Desktop\Boots\Nostale\Java\A ngriff.java mit Java-Compiler
Angriff.java:20:19:...
|
All times are GMT +1. The time now is 04:23.
|
|