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.