2013-07-27 20 views
19

Questo è il mio codice livello di assieme ...Che cos'è _start globale nel linguaggio assembly?

section .text 
global _start 
_start: mov eax, 4 
     mov ebx, 1 
     mov ecx, mesg 
     mov edx, size 
     int 0x80 
exit: mov eax, 1 
     int 0x80 
section .data 
mesg db  'KingKong',0xa 
size equ  $-mesg 

uscita:

[email protected]:~/Arena# nasm -f elf a.asm -o a.o 
[email protected]:~/Arena# ld -o out a.o 
[email protected]:~/Arena# ./out 
KingKong 

La mia domanda è Qual è la _start globale utilizzato per? Ho provato la fortuna con Mr.Google e ho scoperto che è usato per dire il punto di partenza del mio programma. Perchè non ci resta che il _start dire dove si avvia il programma come quello indicato di seguito che produce un avvertimento pò sullo schermo

section .text 
_start: mov eax, 4 
     mov ebx, 1 
     mov ecx, mesg 
     mov edx, size 
     int 0x80 
exit: mov eax, 1 
     int 0x80 
section .data 
mesg db  'KingKong',0xa 
size equ  $-mesg 

[email protected]:~/Arena# nasm -f elf a.asm 
[email protected]:~/Arena# ld -e _start -o out a.o 
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080 
[email protected]:~/Arena# ld -o out a.o 
ld: warning: cannot find entry symbol _start; defaulting to 0000000008048080 
+1

possibile duplicato di ["global main" in Assembly] (http://stackoverflow.com/questions/17882936/global-main-in-assembly) –

risposta

25

global direttiva è NASM specifica. È per esportare i simboli nel codice in cui punta nel codice oggetto generato. Qui si contrassegna il simbolo _start globale, quindi il suo nome viene aggiunto nel codice oggetto (a.o). Il linker (ld) può leggere quel simbolo nel codice oggetto e il suo valore in modo che sappia dove contrassegnare come punto di ingresso nell'eseguibile di output. Quando esegui l'eseguibile, inizia da dove è indicato come _start nel codice.

Se una direttiva global manca per un simbolo, tale simbolo non verrà inserito nella tabella di esportazione del codice oggetto in modo che il linker non abbia modo di conoscere il simbolo.

Se si desidera utilizzare un nome di punto di ingresso diverso da quello _start (che è il default), è possibile specificare -e parametre del D. come:

ld -e my_entry_point -o out a.o 
+1

'_start' è solo il primo" know "per impostazione predefinita. 'ld -o out a.o -e _main' funzionerebbe. –

+0

Cambierò un po 'la mia domanda e poi la mia domanda il mio suono un po' più chiaro ... – vikkyhacks

+0

@vikkyhacks cosa non è chiaro nella mia risposta? la tua domanda non sembra essere cambiata. –

2

L'etichetta non è esplicitamente globale fino a quando si dichiara a essere globale, quindi è necessario utilizzare la direttiva globale.

L'etichetta globale "_start" è necessaria per il linker, se non esiste un indirizzo _start globale, il linker si lamenterà perché non riesce a trovarne uno. Non hai dichiarato _start come globale, quindi non è visibile al di fuori di quel modulo/oggetto di codice, quindi non è visibile al linker.

Questo è l'opposto di C in cui le cose sono implicite essere globale a meno che non li dichiara di essere locale

unsigned int hello; 
int fun (int a) 
{ 
    return(a+1); 
} 

ciao e divertimento sono globali, visibili al di fuori dell'oggetto, ma questo

static unsigned int hello; 
static int fun (int a) 
{ 
    return(a+1); 
} 

li rende locali non visibili.

tutti locali:

_start: 
hello: 
fun: 
more_fun: 

questi sono ormai globale a disposizione del linker e altri oggetti

global _start 
_start: 
global hello 
hello: 
... 
+0

capisce che queste direttive sono specifiche per l'assemblatore, il programma che assembla il linguaggio assembly in codice macchina. I linguaggi di assemblaggio in genere non hanno standard, quindi ogni assemblatore può fare le proprie cose, nota "intel format" vs "at & t format" è un estremo per lo stesso set di istruzioni. Allo stesso modo alcuni potrebbero volere "globale" e altri potrebbero richiedere ".global" per esempio. Quindi stai imparando le sfumature della toolchain non necessariamente il set di istruzioni. –

+0

beh, questo rende davvero molto difficile da digerire, Abbiamo il concetto di variabili locali e globali in C a causa delle funzioni utilizzate, ci sono ambiti in linguaggio assembly (beh, correggimi se ho torto, ho appena iniziato assemblaggio) Perché il linker non può semplicemente cercare _start nel mio programma e impostare il punto di partenza per l'esecuzione? Di quali informazioni manca? – vikkyhacks

+1

@vikkyhacks, immagino si possa pensare alle etichette in assembly come simboli "statici" in un contesto C, almeno per impostazione predefinita. Cioè, sono utilizzabili solo nell'ambito di file/traduzione. Definire un'etichetta con '.global' rende l'assemblatore esportarlo (aggiungerlo alla tabella dei simboli dell'oggetto) in modo che il linker possa trovarlo in seguito per l'uso in altre unità di traduzione (o per l'avvio del programma, nel tuo caso). –

1

_start è impostato secondo le impostazioni di scrittura ld linker:

ld -verbose a.o | grep ENTRY 

uscite :

ENTRY(_start) 

ELF file format (e altri formati di oggetti suppongo), indicare esplicitamente a quale indirizzo verrà avviato il programma attraverso il campo di intestazione e_entry.

ENTRY(_start) indica al linker di impostare tale voce l'indirizzo del simbolo _start durante la generazione del file ELF dai file oggetto.

Quindi, quando il sistema operativo avvia il programma (exec system call su Linux), analizza il file ELF, carica il codice eseguibile in memoria e imposta il puntatore di istruzioni sull'indirizzo specificato.

Il flag -e ha indicato by Sedat sovrascrive il simbolo predefinito _start.

È possibile sostituire lo script del linker predefinito con l'opzione -T <script>.

+0

'ld -o a.o' dice solo" nessun file di input ". Che opzione di riga di comando intendevi? –

+0

@PeterCordes ringraziamenti! Penso che intendessi '-verbose'. –

0

global _start è solo un'etichetta che punta a un indirizzo di memoria. Nel caso di _start quando si tratta di file binari ELF è l'etichetta predefinita utilizzata che funge da indirizzo in cui inizia il programma.

C'è anche main o _main o main_ è noto per il linguaggio C, e viene chiamato da "codice di avvio", che è "di solito" legato a - se si sta utilizzando C.

Spero che questo aiuti.