Verwenden Sie das Label _start
statt main
für den ELF-Einstiegspunkt. main
impliziert, dass es wie C main
ist Funktion, aber dies ist nicht einmal eine Funktion (z. B. können Sie nicht ret
).
Sie sagen es nicht, aber aufgrund der Fehlermeldungen und des Codes gehe ich davon aus, dass Sie Ihren 32-Bit-Code mit nasm -felf32 hello32.asm && ld -melf_i386 -o hello32 hello32.o
erstellen
(Wenn Sie tatsächlich 64-Bit-Code erstellen, haben Sie Glück, dass es zufällig funktioniert, aber es bricht zusammen, sobald Sie irgendetwas mit esp
tun statt rsp
.)
Die Fehlermeldung ist von ld
, nicht von nasm
. So steht es direkt in der Nachricht. Tims Kommentar ist richtig:ld
sucht nach einem _start
Symbol in den verknüpften Dateien, setzt den Einstiegspunkt jedoch auf den Anfang des Textsegments, wenn es keinen findet.
Es spielt keine Rolle, welche anderen globalen/externen Symbole Sie definieren. main
hat hier überhaupt keine Relevanz und könnte überall hin zeigen, wo Sie wollen. Es ist nur nützlich für eine Disassemblierungsausgabe und ähnliches. Ihr Code würde genauso funktionieren, wenn Sie global main
herausnehmen würden / main:
Zeilen oder ändern Sie sie in einen anderen Namen.
Kennzeichnung als main
ist unklug, da der ELF-Einstiegspunkt keine Funktion ist . Es ist nicht main()
, und erhält argc
nicht und argv
Argumente und kann nicht ret
weil ESP auf argc
zeigt anstelle einer Absenderadresse.
Verwenden Sie nur main
wenn Sie mit dem CRT-Startcode von gcc / glibc verknüpfen, der nach einem main
sucht Symbol und ruft es nach der Initialisierung von libc auf. (Funktionen wie printf funktionieren also. Technisch dynamische Linker-Hooks lassen libc sich selbst vor Ihrem _start
initialisieren wenn Sie es verlinkt haben, aber tun Sie das im Allgemeinen nicht, es sei denn, Sie verstehen genau, was Sie tun). Verwandt:Assemblieren von 32-Bit-Binärdateien auf einem 64-Bit-System (GNU-Toolchain)
z.B. gcc -m32 -no-pie -o hello main.o
wenn Sie einen main:
definieren
statt gcc -m32 -static -nostdlib -o hello start.o
(was Ihrem bloßen ld
entspricht ).
(In den letzten Jahren haben Linux-Distributionen GCC mit -pie
konfiguriert als Standard, der positionsunabhängigen Code will. Aber das ist im 32-Bit-Modus ohne RIP-relative Adressierung (sehen Sie sich zum Beispiel die Ausgabe von GCC asm an) wirklich unpraktisch und bedeutet ld
konvertiert call printf
nicht in call [email protected]
für dich. Für die meisten handgeschriebenen Asms, die den meisten Tutorials folgen, möchten Sie also traditionelle ausführbare Nicht-PIE-Dateien, sodass keine Textverschiebungen erforderlich sind.)
Ich würde vorschlagen, dass Sie Ihre Objektdateien (wie auch immer sie erzeugt werden) mit gcc
verknüpfen , nicht ld
.
gcc
ruft ld
auf mit den entsprechenden Optionen, da es mehr über den Quellcode weiß und alles Notwendige für die Annahmen erstellt, dass ld
macht.