Maschinenroutine in C++
-
Hallo, Leute.
Nachdem ich mich informiert habe, wie man einen Zeiger auf eine Funktion definiert, habe ich ein neues Problem, und weiß nicht, wie ich es lösen kann.
Ich möchte gerne in einem Speicherbereich eine Maschinenroutine speichern
(wofür und warum ist erstmal zweitranging) und diese dann innerhalb vom Programm aufrufen. Das ganze stelle ich mir in etwa so vor:// Beispiel.cpp // ------------ #incude <iostream> using namespace std; void Zeichen(char c) { char *Asm = new char[7]; // Befehle speichern: Asm[0] = 0xB2; Asm[1] = c; // MOV DL, c Asm[2] = 0xB4; Asm[3] = 2; // MOV AH, 2 Asm[4] = 0xCD; Asm[5] = 0x21; // INT 21h Asm[6] = 0xCB; // RETF // Aufrufen: Asm; // oder: Asm(); ? oder wie? } int main() { cout << "Jetzt wird ein A ausgegeben:" << endl; Zeichen('A'); cout << endl << "Stimmt." << endl; return 0; }Ich habe aber schon mehrere Varianten von Zeile 17 ausprobiert, z.B. per
Funktionszeiger auf Asm, aber egal, wie ich's anstelle:
Je nach Variante geschieht entweder nichts
- sprich ich erhalte folgende Ausgabe:Jetzt wird ein A ausgegeben: Stimmt.Oder der Compiler bringt mir eine Fehlermeldung, die besagt, dass er die Typen nicht umwandeln kann ( char* und char(*)() ), oder Asm nicht als Funktion verwendet werden kann.
Wer kann mir bitte, bitte helfen.
Danke bereits im Voraus.
-
Ich weiss nicht ob es vom Betriebssystem und vom Compiler abhängt.
Bei mir kann man im Quellcode Assemblerbefehle so einbinden:__asm mov al, 2Schau mal in der Doku deines Compilers nach.
-
Ja das kann ich mit asm auch,
aber ich möchte auch mal Maschinencode einbinden,
z.B. könnte ich den ja in einer externen Datei speichern und
benötige ihn dann und dann muss der ja irgendwo gespeichert werden
und von da aus aufgerufen.
Deswegen.
-
Vgl. Daten vs. Code. Daten können nicht ohne weiteres ausgeführt werden. Der ISO C++ hat sowas von keine Ahnung davon...
greetz, Swordfish
-
Lol, das sieht aus wie der VB6-Inline-ASM-Hack. Wenn man mal von eventuellen NX-Flags absieht, könnte das sogar klappen. Man müsste nur den Zeiger auf einen Funktionszeiger casten. Dafür muss man aber den Umweg über 'void*' gehen, weil man nicht direkt casten darf:
void* pv = ASM; void (*fun)() = static_cast<void (*)()>(pv); fun();(Von solchen Späßchen ist natürlich abzuraten!)
-
Konrad Rudolph schrieb:
Lol, das sieht aus wie der VB6-Inline-ASM-Hack. Wenn man mal von eventuellen NX-Flags absieht, könnte das sogar klappen. Man müsste nur den Zeiger auf einen Funktionszeiger casten. Dafür muss man aber den Umweg über 'void*' gehen, weil man nicht direkt casten darf:
void* pv = ASM; void (*fun)() = static_cast<void (*)()>(pv); fun();(Von solchen Späßchen ist natürlich abzuraten!)
vor allem, weil nicht garantiert ist, dass void* und funktionszeiger dieselbe größe haben. (auch wenn es afaik auf allen POSIX system garantiert ist)
deshalb darf man ja auch keinen funktionszeiger nach void* casten.
-
queer_boy schrieb:
vor allem, weil nicht garantiert ist, dass void* und funktionszeiger dieselbe größe haben. (auch wenn es afaik auf allen POSIX system garantiert ist)
deshalb darf man ja auch keinen funktionszeiger nach void* casten.Hmm, da hattu recht. Wieso erlaubt mir das der VC++-Compiler dann eigentlich? Dummes Ding.

– Ist aber auch wurst, funktioniert eh nicht.
-
Konrad Rudolph schrieb:
Hmm, da hattu recht. Wieso erlaubt mir das der VC++-Compiler dann eigentlich? Dummes Ding.

weil unter windoofs ein function pointer auch nur 32 bit hat, wie alle anderen pointer auch und der prozessor im 'flat memory model' läuft. auf systemen mit verschiedenen pointerbreiten (far, near, ...), und/oder paged memory bekommste vom compiler entsprechende warnings, wenn etwas nicht passen sollte...

-
Wieso nicht so?
void call_asm_thingy(void* asm_thingy) { __asm mov eax, asm_thingy __asm call eax }
-
warum nehmt ihr nicht einfach:
__asm__ /*__volatide__ */ ("movl ...");? Könnt ihr doch direkt Asemmbly-Befehle ausführen.