Utilizza l'etichetta _start
invece di main
per il punto di ingresso ELF. main
implica che è come il C main
funzione, ma questa non è nemmeno una funzione (ad esempio non puoi ret
).
Non dici, ma dai messaggi di errore e dal codice presumo che tu stia costruendo il tuo codice a 32 bit con nasm -felf32 hello32.asm && ld -melf_i386 -o hello32 hello32.o
(Se stai effettivamente costruendo codice a 64 bit, sei fortunato che funzioni, ma si romperà non appena fai qualcosa con esp
invece di rsp
.)
Il messaggio di errore proviene da ld
, non da nasm
. Lo dice proprio nel messaggio. Il commento di Tim è corretto:ld
cerca un _start
simbolo nei file che collega, ma imposta il punto di ingresso all'inizio del segmento di testo se non ne trova uno.
Non importa quali altri simboli globali/esterni definisci. main
non ha alcuna rilevanza qui e potrebbe puntare ovunque tu voglia. È utile solo per un output di disassemblaggio e cose del genere. Il tuo codice funzionerebbe esattamente allo stesso modo se estrai il global main
/ main:
linee o cambiarle con qualsiasi altro nome.
Etichettandolo come main
non è saggio perché il punto di ingresso ELF non è una funzione . non main()
e non riceve argc
e argv
argomenti e non può ret
perché ESP punta a argc
invece di un indirizzo di ritorno.
Usa solo main
se ti colleghi con il codice di avvio CRT di gcc / glibc che cerca un main
symbol e lo chiama dopo aver inizializzato libc. (Quindi funzioni come printf funzionano. Gli hook del linker tecnicamente dinamici consentono a libc di inizializzarsi prima del tuo _start
se l'hai collegato, ma generalmente non farlo a meno che tu non capisca esattamente cosa stai facendo). Correlati:Assemblaggio di binari a 32 bit su un sistema a 64 bit (toolchain GNU)
per esempio. gcc -m32 -no-pie -o hello main.o
se definisci un main:
invece di gcc -m32 -static -nostdlib -o hello start.o
(che è equivalente al tuo semplice ld
).
(Negli ultimi anni, le distribuzioni Linux hanno configurato GCC con -pie
come impostazione predefinita, che richiede codice indipendente dalla posizione. Ma questo è davvero scomodo in modalità a 32 bit senza indirizzamento relativo a RIP (guarda ad esempio l'output di GCC asm) e significa ld
non convertirà call printf
in call [email protected]
per te. Quindi, per la maggior parte degli asm scritti a mano seguendo la maggior parte dei tutorial, si desidera eseguibili tradizionali non-PIE, quindi non sono necessarie rilocazioni di testo.)
Suggerirei di collegare i tuoi file oggetto (comunque siano prodotti) con gcc
, non ld
.
gcc
chiamerà ld
con le opzioni appropriate, poiché sa di più sul codice sorgente e creerà tutto ciò che è necessario per le ipotesi che ld
rende.