Discussion:
DLL Funktion in Assembler aufrufen ...
(zu alt für eine Antwort)
Jens Kallup
2022-04-15 15:16:37 UTC
Permalink
Hallo,
ich wÃŒrde gerne mal Wissen, wie man mit den GNU-artiken
Assembler-Code Funktionen die sich in anderen .DLL Dateien
befinden aufruft.

Oder macht das ganz alleine der Linker ?

Ich mein, um dann auch auf die Funktion zuzugreifen bedarf
es doch Assembler-Code, auch wenn der in diesen Fall klein
aussehen sollte ?

Gruß, Jens
Herbert Kleebauer
2022-04-15 20:06:53 UTC
Permalink
Post by Jens Kallup
Hallo,
ich würde gerne mal Wissen, wie man mit den GNU-artiken
Assembler-Code Funktionen die sich in anderen .DLL Dateien
befinden aufruft.
Oder macht das ganz alleine der Linker ?
Ich mein, um dann auch auf die Funktion zuzugreifen bedarf
es doch Assembler-Code, auch wenn der in diesen Fall klein
aussehen sollte ?
Ich verstehe die Frage nicht so ganz. Willst du wissen
was du bei einem ganz bestimmten Assembler angeben musst
um eine DLL Funktion aufzurufen (dann schau einfach
ein Beispielprogramm für diesen Assembler an) oder
willst du wissen, welche Befehlsfolgen und Datenstrukturen
in der exe stehen um den Aufruf auszuführen (das hat dann
aber nichts mit "GNU-artiken Assembler-Code" zu tun).
Stefan Reuther
2022-04-16 08:05:16 UTC
Permalink
Post by Jens Kallup
ich würde gerne mal Wissen, wie man mit den GNU-artiken
Assembler-Code Funktionen die sich in anderen .DLL Dateien
befinden aufruft.
Schreib ein kleines C-Modul, das eine Funktion aus einer DLL aufruft,
und schau nach, was der Compiler draus macht.
Post by Jens Kallup
Oder macht das ganz alleine der Linker ?
Ich mein, um dann auch auf die Funktion zuzugreifen bedarf
es doch Assembler-Code, auch wenn der in diesen Fall klein
aussehen sollte ?
Das kommt halt drauf an, welchen Assembler-Code man genau schreibt.

Du kannst normalerweise Funktion aus DLLs direkt aufrufen, wie jede
andere Funktion auch ('call whatever'). Je nach Art der DLL und
Zielbetriebssystem braucht der Linker dann noch etwas Hilfe, um das
zusammenzubauen. Das ist allerdings nicht immer die effizienteste Lösung
des Problems. Ob und wie man das effizienter bekommt, hängt dann von der
Umgebung ab.


Stefan
Jens Kallup
2022-04-17 15:31:47 UTC
Permalink
Hallo Ihr beiden,

ich bin schon wieder mit etwas neueren Informationen hier gestrandet:

Im Moment beschÀftige ich mich damit, die .EXE cutables, die mit dem
FPC (Free Pascal Compiler) 3.2.0 etwas kleiner zu machen, so dass man
am Ende minimalen binÀr Code erhÀlt.

Dazu habe ich bereits schon 2021 damit angefangen, ist dann aber doch
etwas ins stocken gekommen, und die Sachlage hat sich inzwischen ein
wenig geÀndert.

Im Projekt habe ich mit der 64-Bit Version von IDA 7 ein Assembly von
meinen Projekt (.exe + .dll) erhalten, bei dem ich im Moment nicht so
ganz durchblicke.

Und zwar mÃŒsste fÃŒr die (im Moment bestehende Funktion: nullsub_1 ein
Puffer Label entstehen, damit dann das Programm etwas damit anfangen
kann.
Den eigentliche Code habe ich mittels FPC 3.2.0 erstellen lassen, was
man im Makefile
zu diesen Projekt entnehmen kann.
Als Entwicklungs-Umgebung habe ich:
- Windows 10/11
- MinGW-64 Bit
- und die zu MinGW-64 MYS gehörende POSIX Std.Programme wie
- sed
- ...
genutzt.
Das Makefile ist etwas speziefisch auf meine Umgebung ausgelegt, was
dann evtl. umgeschrieben werden muss.
Ein paar Kommentare auf Englisch sind dann aber auch enthalten.
Als make.exe habe ich die GNU artige Version, die mit MSYS installiert
werden kann, verwendet.

Hier ist der Ausschnitt zu diesen Code, der vom Compiler erzeugt
wurde und mittel IDA 7 wieder disassembliert wurde:

public start
start proc near

var_8= qword ptr -8

push rbp
mov rbp, rsp
lea rsp, [rsp-30h]
mov [rbp+var_8], 0
nop
lea rax, nullsub_1 ; <--- hier

lea rdx, aHalloXxl ; "hallo xxl "
mov rcx, rax
call fpc_ansistr_assign
; in C geschrieben: void* fpc_ansistr_assign(void* dst, void* src);

; ab hier sollte es dann normal weiter gehen
; macht es auch, aber siehe den code oberhalb ...
;
mov rcx, qword ptr cs:nullsub_1
call _$dll$laz_rtl$LengthString
movsx ecx, ax
call _$dll$laz_rtl$WriteLnInteger
lea rcx, aMeerjung ; "meerjung"
call _$dll$laz_rtl$WriteLnString
lea rcx, [rbp+var_8]
call _$dll$laz_rtl$ReadLn
lea rcx, [rbp+var_8]
call fpc_ansistr_decr_ref
mov ecx, 1
call _$dll$laz_rtl$LazExitProcess
nop
nop
mov rcx, rbp
call sub_7FF66A4A1060
mov ecx, 0 ; uExitCode
mov rax, cs:ExitProcess
call rax ; ExitProcess
nop
lea rsp, [rbp+0]
pop rbp
retn
start endp

Und hier könnt Ihr gerne vom github.com das Projekt downloaden:

https://github.com/paule32/mini_fpc_windows

In der test1.pas Datei, die sich im Verzeichnis sample befindet
könnt Ihr entnehmen, dass das vorliegende Problem in Zeile: 11
zu suchen ist.
Dort verlangt der FPC das Symbol fpc_ansistr_assign, was, so
denke ich keine Funktion, sondern eine Addresse mit den Puffer
sein sollte.

Jetzt habe ich so viel geschrieben ...
Wenn was nicht klar sein sollte, oder noch Informationen fehlen,
so bin ich auf RÃŒckantwort gerne dankbar, und werde dienlich bei
stehen.

Mit freundlichen GrÌßen
Jens
Jens Kallup
2022-04-17 17:47:57 UTC
Permalink
vergessen zu teilen:

https://dpaste.com/8JHWZ3BNV#line-90

ab Zeilen: 90, ...

die wichtigste ist wohl Zeile: 92.
wie kann man einen Puffer anlegen, der
dann von fpc_ansistr_assign bearbeitet
werden kann ?
Also nullsub_1 ist gegenwÀrtig eine
Funktion, aber da sollte ein Zeiger
auf den Puffer hinweisen.

Jens
Stefan Kanthak
2022-04-20 18:30:06 UTC
Permalink
Post by Jens Kallup
Hallo,
ich würde gerne mal Wissen, wie man mit den GNU-artiken
Assembler-Code Funktionen die sich in anderen .DLL Dateien
befinden aufruft.
.DLL bedeutet, dass die Laufzeit-Umgebung Windows mit x86/AMD64
Prozessor ist: der Funktionsaufruf erfolgt dort ganz trivial mittels
CALL <symbol> = E8 <adresse>
oder
JMP <symbol> = E9 <adresse>
nachdem Du ggf. von der Funktion <symbol> erwartete Argumente
gemaess der jeweiligen Aufrufkonvention in die passenden Register
sowie auf den Stack geladen hast.
Siehe <https://msdn.microsoft.com/en-us/library/984x0h58.aspx>
Post by Jens Kallup
Oder macht das ganz alleine der Linker ?
Nein: der LADER (ueber)schreibt die 4 Byte lange (relative) <adresse>,
die der Compiler als 0x00000000 generiert und deren Position im Code
er dem Linker (und damit indirekt auch dem Lader) ueber die IMPORT-
Tabelle bekannt gemacht hat, mit der (relativen) Adresse des geladenen
Symbols; dessen Namen sowie Adresse findet er in der EXPORT-Tabelle
der DLL.

Siehe <https://msdn.microsoft.com/en-us/library/ms809762.aspx>,
<https://msdn.microsoft.com/en-us/library/bb985992.aspx> und
<https://msdn.microsoft.com/en-us/library/bb985994.aspx> sowie
<https://msdn.microsoft.com/en-us/library/ms680547.aspx>

JFTR: unter Windows wird vom LINKER typischerweise eine STATISCHE
*.lib eingebunden, die Stubs fuer alle exportierten Funktionen
<symbol> einer DLL enthaelt; CALL bzw. JMP springen diese Stubs
an, und diese dann per JMP die importierten Funktionen.
So muss die Adresse einer importierten Funktion nur an einer
Stelle des gesamten Codes/Programms eingesetzt werden.

Stefan
--
<https://www.duden.de/rechtschreibung/Kanthaken>
Loading...