Assembler DLLs für BB
Übersicht BlitzBasic FAQ und Tutorials
Willi die RübeBetreff: Assembler DLLs für BB |
So, Aug 03, 2008 15:56 Antworten mit Zitat |
|
---|---|---|
Um hier auch mal etwas mehr oder weniger sinnvolles beizusteuern, hab ich mal ein kleines HowTo geschrieben, für alle die mal die Lust verspüren Assembler in ihren Projekten einzubauen.
Assemblerkentnisse sind für den richtigen Einsatz natürlich aufjeden Fall Pflicht, allerdings denke ich, dass dieses HowTo hier auch für andere interessant sein könnte. Zum Einsatz kommt hier FASM, wobei ich allerdings versuche auf die Makros verzichten, damit die Portierung in andere Assembler nicht allzuschwer sein dürfte. Nun denn, beginnen wir mit dem Header: Code: [AUSKLAPPEN] format PE GUI 4.0 DLL
entry DllMain Die erste Zeile gibt das Dateimodell für den Assembler an und in der zweiten Zeile wird der Einstiegspunkt festgelegt, in BB muss dieser DllMain lauten, sonst stützt das Programm ab. Gehen wir mal davon aus, wie benötigen keine zusätzlichen Variablen und beginnen gleich mit dem Codeblock: Code: [AUSKLAPPEN] section '.code' code readable executable
Kleine Information: Wenn das eax Register auf 0 ist, wird die Dll nicht gestartet.
DllMain: ; obligatorische DllMain Funktion mov eax,1 ret Dann können wir unsere Funktionen zusammenbasteln. Zum Test mal eine simple Additionsfunktion: Code: [AUSKLAPPEN] MyAdd:
Hab es mal für alle die kein ASM beherrschen ein wenig überkommentiert.
push ebp ;alten Basepointer im Stack speichern mov ebp,esp ;neuer Basepointer = Stackpointer add esp,8 ; Stackpointer um die Größe der Parameter erhöhen(2xDouble Words=8 Byte) pop eax ; Erster Parameter vom Stack in eax speichern pop ebx ; Zweiter Parameter vom Stack in ebx speichern add eax,ebx ; Register addieren; Ergebnis in eax mov esp,ebp ;neuer Stackpointer = aktueller Basepointer pop ebp ;alten Basepointer vom Stack wiederherstellen ret Wichtig: Übergebene Parameter werden von BB auf den Stack geschoben, von wo man sie zur Benutzung in der Funktion wieder runterholen muss. Den Rückgabewert holt BB dann aus dem eax Register. So, nun wirds schon etwas verzwickter, denn jetzt kommt der Exportblock. Der Aufbau des Headers ist strikt vorgegeben und noch relativ uninteressant: Code: [AUSKLAPPEN] section '.edata' export data readable
Eine RVA ist eine (zur Startadresse des Programmes relative) Adresse im Ram.
dd 0 ; Unbenutzt dd 0 ; Zeitstempel(optional) dd 0 ; Unbenutzt/ eigt. Versionsinformationen dd RVA dllname ; relative virtuelle Addresse(RVA) des DLL Dateinamens dd 0 ; Beginn der Zuordnungszahlen dd 1 ; Anzahl der Funktionen dd 1 ; Anzahl der Funktionsnamen dd RVA ExportAdressTable ; RVA der Adressentabelle(EAT) dd RVA ExportNamesTable ; RVA der Namentabelle(ENT) dd RVA Ordinals ; RVA zur Zuordnungstabelle Danach können wir auch gleich schon unser dllname Label von oben definieren: Code: [AUSKLAPPEN] dllname db 'test.dll',0
Nun kommen wir zu dem interessanten Teil, nämlich unsere drei Tabellen bzw. genauergenommen eigentlich Arrays: ENT(Namenstabelle): Hier drin stehen die RVAs der Namenlabels, unter denen man später die Funktionen importiert. Die Einträge müssen alphabetisch korrekt sortiert sein, sonst kann es vorkommen, dass Windows die Funktion nicht findet. Zuordnungszahlentabelle: Die Einträge sind in paralleler Reihenfolge mit denen der ENT verknüpft. Der Wert selber verweißt auf einen Eintrag in der EAT. EAT(Adressentabelle): Hier stehen die RVAs der Funktionen selbst drin. Lange Erklärung, kurzer Code: Code: [AUSKLAPPEN] ExportNamesTable:
dd RVA _MyAdd ; RVA des Funktionsnamens Ordinals: dw 0 ; Zuordnungszahl ExportAdressTable: dd RVA MyAdd ; RVA der Funktion _MyAdd db 'MyAdd',0 ;Funktionsname Aufgrund der Tatsache, dass wir in unserem Beispiel nur eine Funktion haben, sieht dies noch recht einfach aus. Machen wir mal ein anderes Beispiel: Code: [AUSKLAPPEN] ; Funktionsnamen/adressen Anzahl im Header müssen natürlich angepasst werden!
Sieht doch gleich viel witziger aus, oder nicht?
ExportNamesTable: ; Alphabetische Reihenfolge dd RVA _HisAdd dd RVA _MyAdd dd RVA _OurAdd dd RVA _TheirAdd dd RVA _YourAdd Ordinals: dw 2 ; HisAdd ist der dritte Eintrag in der EAT dw 0 ; MyAdd ist der erste Eintrag in der EAT dw 3 ; usw. dw 4 dw 1 ExportAdressTable: dd RVA MyAdd dd RVA YourAdd dd RVA HisAdd dd RVA OurAdd dd RVA TheirAdd _MyAdd db 'MyAdd',0 _YourAdd db 'YourAdd',0 _HisAdd db 'HisAdd',0 _OurAdd db 'OurAdd',0 _TheirAdd db 'TheirAdd',0 Dann belassen wir es mal hierbei und putzen den Ram: Code: [AUSKLAPPEN] section '.reloc' fixups data discardable
Unser kompletter Code sieht dann so aus: Code: [AUSKLAPPEN] format PE GUI 4.0 DLL
entry DllMain section '.code' code readable executable DllMain: mov eax,1 ret MyAdd: push ebp mov ebp,esp add esp,8 pop eax pop ebx add eax,ebx mov esp,ebp pop ebp ret section '.edata' export data readable dd 0 dd 0 dd 0 dd RVA dllname dd 0 dd 1 dd 1 dd RVA ExportAdressTable dd RVA ExportNamesTable dd RVA Ordinals dllname db 'test.dll',0 ExportNamesTable: dd RVA _MyAdd Ordinals: dw 0 ExportAdressTable: dd RVA MyAdd _MyAdd db 'MyAdd',0 section '.reloc' fixups data discardable Dies können wir nun kompilieren(FASM erkennt anhand vom Header automatisch, dass es sich um eine DLL handelt). Die dazugehörige Userlib: Code: [AUSKLAPPEN] .lib "test.dll"
Add%(value1%,value2%):"MyAdd" Und folgender Code funktioniert: Code: [AUSKLAPPEN] Print Add(-14,15)
WaitKey() End Perfekt ---------------------------------------------------------------- Ein Vorteil von FASM sind natürlich die Macros mit der sich sehr viel vereinfachen lässt. Mithilfe von Macros würde der Code so aussehen: Code: [AUSKLAPPEN] format PE GUI 4.0 DLL
Sieht also schon wesentlich übersichtlicher und verständlicher aus.
entry DllMain include '%fasminc%\win32a.inc' section '.code' code readable executable proc DllMain mov eax,TRUE ret endp proc MyAdd value1,value2 mov eax, [value1] add eax, [value2] ret endp section '.edata' export data readable export 'test.dll',\ MyAdd, 'MyAdd' section '.reloc' fixups data discardable ---------------------------------------------------------------- So weit so gut, Feedback, Fragen, Kritik oder irgendwelche Fehler bitte hier posten. Mfg Willi |
||
Ich habe keine Lösung, aber ich bewundere das Problem.
Tehadon Q6600, MSI Neo2-FR, 4GB Ram, nVidia 7800 GTX At the Farewell Party visit: MySpace | Homepage |
Kaddy |
So, Jun 21, 2009 11:20 Antworten mit Zitat |
|
---|---|---|
kleine frage^^
Wenn ich jetz in bb mit assemblern arbeite und dies dann übersetze habe ich doch den gleichen effeckt also die exe bleibt unverändert, oder wie das ganze system nahe angesteuert? ich meine ist es das gleiche im endeffeckt wenn ich Code: [AUSKLAPPEN] DATA SEGMENT
Meldung db "Hello World" db "$" DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA Anfang: mov ax, DATA mov ds, ax mov dx, offset Meldung ; mov ah, 09h int 21h mov ax, 4C00h int 21h CODE ENDS END Anfang oder Code: [AUSKLAPPEN] Print "Hello World" waitkey end verwände? müsste das ganze nicht dann auch auf linux laufen wenn ich es dann übersetze oder ist und bleibt es dann einfach nur ein bb prog .D ich hoffe es war verständlich wie ich es meinte[/code] |
||
Bin Aktuell auf der Suche nach einen Programmierer Team, ob Hobby Team oder Firma ist egal. Einfach eine PM an mich schreiben.
Bezahlung verlange ich NATÜRLICH keine Es gibt 10 arten von Menschen, die einen verstehen das Binärsystem , die anderen nicht |
flona |
So, Jun 21, 2009 12:04 Antworten mit Zitat |
|
---|---|---|
Nein es läuft nicht auf Linux, da der Compiler nur unter Windows läuft und auch nur auf Windows ausführbare Dateien erstellt. Die ganzen Header der EXE und was weiß ich läuft nicht unter Linux(Korrigiert mich wenn ich falsch liege).
Außerdem bin ich mir sicher, dass BB nicht mit Interupts wie in deinem Beispiel arbeitet, sondern mit WinApi Befehlen(WriteConsole, ...). Zu deiner Frage ob die Datei dann anders ist: Die Runtimefunktionen wie Print, WaitKey, ... werden immer IN die EXE eingebunden. Wenn du das ganze als Dll in ASM schreibst ist der Code in der Dll Datei AUSgelagert, die dann wiederrum von BB dynamisch eingebunden wird. Ich hoffe ich habe mich nicht allzu unverständlich ausgedrückt |
||
www.Dreier-Florian.kilu.de
Intel Core 2 Quad Q9400 | Zotac 9800GT | 4GB RAM | 1TB HDD | Windows 7 Professional 32bit |
Tankbuster |
So, Jun 21, 2009 12:10 Antworten mit Zitat |
|
---|---|---|
Assembler kannst du direkt an den Prozessor schicken, aber Windows-Executables laufen eben nur unter Windows, da Windows sie erstmal interpretieren muss, und dann an den Prozessor schickt.
Zitat: müsste das ganze nicht dann auch auf linux laufen wenn ich es dann übersetze oder ist und bleibt es dann einfach nur ein bb prog .D
Durch diese Methode hier, erreichst du einfach, dass dein ASM-Code auf Windows einfach so als Windows-Executable ausgeführt werden kann. Das ganze wird hinterher ja als .exe kompiliert. Außerdem sind die Blitz-exen immer ziemlich groß, da noch der ganze Funktionsumfang von Blitz mit eingebunden ist. Auf Linux wird das ganze daher nicht laufen |
||
Twitter
Download Jewel Snake! Windows|Android |
Kaddy |
So, Jun 21, 2009 20:34 Antworten mit Zitat |
|
---|---|---|
vielen dank für die antworten.
Also bleibt es ebend Blitz Das wäre jetz natürlich zu schön gewesen die Blitz ide als assembler zu verwänden ^^ |
||
Bin Aktuell auf der Suche nach einen Programmierer Team, ob Hobby Team oder Firma ist egal. Einfach eine PM an mich schreiben.
Bezahlung verlange ich NATÜRLICH keine Es gibt 10 arten von Menschen, die einen verstehen das Binärsystem , die anderen nicht |
Übersicht BlitzBasic FAQ und Tutorials
Powered by phpBB © 2001 - 2006, phpBB Group