Einzelnen Beitrag anzeigen
Alt 08.08.2006, 11:49   #1 (permalink)
boonz
Tokio Hotel Fan 10 Jahre hx3
500 Beiträge1000 Beiträge
 
Benutzerbild von boonz
 
Registriert seit: 04.05.2005
Ort: Bahamas
Alter: 32
Beiträge: 1.460
boonz eine Nachricht über ICQ schicken boonz eine Nachricht über Skype™ schicken
Standard [w32 asm]Dynamic Link Libraries

Tach,

da ich grade ein bisschen Assembler mache, dachte ich mir, dass es vielleicht jemanden interessiert. Bücher & Hefte raus, jetzt wird gelernt

Dynamic Link Libraries

Dabei handelt es sich um eine unter Windows verwendete Programmbibliothek. Sie haben das gleiche Format wie .exe - Dateien, enthalten also auch Opcodes, Ressourcen usw., enden aber auf .dll .

Warum?

Warum soll ich meinen Programm-Code in einer DLL verpacken, wenn ich es auch genausogut in die eigentliche Anwendung schreiben kann?
Ganz einfach: Ich bin vielleicht nicht der einzige, der den Kram in der DLL brauch! Vielleicht wollen andere Anwendungen auch gerne darauf zugreifen, aber das geht wohl schlecht, wenn es in meiner .exe eingebunden ist. Das führt natürlich auch zu ziemlicher Arbeits-Speicher-Schon-Tour: Die Datei muss nur einmal in den Speicher geladen werden und kann von da so oft wie nötig benutzt werden.

Es gibt sogar noch einen Vorteil, die sog. "Modularität":
Sagen wir, in der DLL seien irgendwelche Funktionen archiviert. Nun müssen aber einige dieser Funktionen geändert / geupdatet werden, wieauchimmer. Anstatt jetzt in allen Anwendungen diese Funktionen ändern zu müssen, nimmt man die Änderungen einmal an der DLL vor und alle Programme sind geupdatet. Im großen Stil wie z.B. beim Office Paket o.Ä. führt das natürlich zu enormen Arbeits-Vereinfachung.

DLLs werden auch gerne in noch einer anderen Fuktion verwendet: Als Plug-Ins.
Ich möchte gerne eine kleine Erweiterung zu meinem Lieblings-Programm schreiben. Eine koch-mir-den-kaffee-funktion. Kein Problem:
Den Code in einer DLL verfassen, Plug-In im Programm aktivieren, fertig ist. Dynamische Einbindbarkeit, Dynamic Linking

Wie?

Schön, schön, wie sieht das Ganze in der Praxis aus?
Nun, Windows bietet zwei Möglichkeiten, eine DLL einzubinden:

Implizit:
Windows lädt die DLL automatisch mit dem Client-Programm (das Programm, das die DLL "anfordert"), bevor der Client ausgeführt wird, sodass er auf die DLL zugreifen kann.
Diese Methode ist ratsam, wenn der Client mindestens eine Prozedur aus der DLL braucht, da Windows es ja sowieso in den Speicher lädt, da wir es Windows ja implizit mitgeteilt haben.

Explizit
Was passiert aber, wenn die DLL-Datei gar nicht da ist? Die Anwendung wird gar nicht erst gestartet werden. Das lässt sich mit explizitem Einbinden vermeiden:
Hierbei lädt Windows die DLL erst, wenn der erste Client die DLL während des Ausführens "anfordert".

Zum Anfordern verwendet man (unter Assembly) folgende Funktionen:
LoadLibrary - um die DLL in den Speicher zu laden
GetProcAddress - um die Adresse der jeweiligen Funktionen zu erlangen
FreeLibrary - um die DLL wieder aus dem Speicher "freizulassen", weil sie nicht mehr gebraucht wird

Wie genau?

Nun, DLLs enthalten exportierte & nicht-exportierte Funktionen, sprich publike und private Funktionen. Die exportierten Funktionen dienen dem Client, wohingegen dieser von den privaten nichts weiß, diese dienen der DLL intern.

Jede DLL hat einen Einsprungspunkt (Entrypoint). Dieser wird vom System "angesprochen", wenn ein Client nach der DLL verlangt. Im Einsprungspunkt kann die DLL auch Speicherplatz reservieren.

Ein typischer Einsprungspunkt ist so aufgebaut:

Code:
BOOL WINAPI DllEntryPoint(

    HINSTANCE hinstDLL,	// handle to DLL module 
    DWORD fdwReason,	// reason for calling function 
    LPVOID lpvReserved 	// reserved 
   );
Es werden also beim Aufruf des Einsprungpunktes drei Parameter weitergegeben, von denen der dritte aber nicht benutzt wird.

hInstDLL ist der module handle der DLL. Eine Art Erkennungsmarke der DLL, die sich nicht ändert, es sei denn die DLL wird neu-geladen.

fdwReason kann vier verschiedene Werte haben:
  • DLL_PROCESS_ATTACH - das nutzt man, wenn die DLL zum ersten Mal in den Speicher gelesen wird. Es dient zur Initialisierung.
  • DLL_PROCESS_DETACH - hiermit wird die DLL aus dem Speicher gelesen. Man kann zB. Speicher wieder freigeben.
  • DLL_THREAD_ATTACH - man erzeugt einen neuen Thread.
  • DLL_THREAD_DETACH - ein Thread im Prozess wird wieder gelöscht.

Funktionen in der DLL können irgendwo abgelagert werden, aber wenn sie exportiert werden sollen, dann müssen sie zusätzlich in einer .DEF-Datei verzeichnet sein. Dazu später.

Das DLL-Skelett

*Bemerkung: Ich verwende MASM-Syntax & -Bibliotheken

DLLSkelett.asm
Code:
.386 
.model flat, stdcall 
option casemap:none 

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib

.data

.data?

.code

DLLEntry proc hInstDLL:DWORD, reason:DWORD, unused:DWORD
	
	.if reason == DLL_PROCESS_ATTACH	; Initialisierung,wenn die DLL geladen wird
		mov eax,TRUE			; eax muss TRUE sein, damit die DLL läuft
	.elseif reason == DLL_PROCESS_DETACH	
		; Code für das Entladen der DLL
	.elseif reason == DLL_THREAD_ATTACH		
		; Thread im Prozess starten
	.elseif reason == DLL_THREAD_DETACH		 
		; Thread im Prozess zerstören
	.endif
	Ret
	
DLLEntry Endp

ExpFunc1 proc
	; Code für die erste Funktion
	Ret
ExpFunc1 EndP

ExpFunc2 proc
	; Code für die zweite Funktion
	Ret
ExpFunc2 EndP

ExpFunc3 proc
	; Code für die dritte Funktion
	Ret
ExpFunc3 EndP

end DLLEntry
Skelett.def

Code:
LIBRARY   DLLSkelett
EXPORTS  _ExpFunc1   @   01  
               _ExpFunc2   @   02
               _ExpFunc3   @   03
Hehehe, ich halte den Programmcode für ziemlich selbst-erklärend. Später mehr dazu, wie man die Funktionen dann auch aufrufen kann.

*P.S.:

Für Code-Beispiele in Hochsprachen siehe Wikipedia:
Dynamic Link Library - Wikipedia
__________________
Zitat:

"Sodomy non sapiens."
- Pterry (Mort)

o
L_
OL
"This is Schäuble. Copy Schäuble into your signature to help him on his way to Überwachungsstaat."

"Tokio Hotel Fan" -edited by Burns :P
- auch edited by Burns :P
boonz ist offline   Mit Zitat antworten