2015-12-06 55 views
9

Sto imparando il montaggio con NASM per una lezione che ho al college. Vorrei collegare la libreria di runtime C con ld, ma non riesco proprio a spiegarmi. Ho una macchina 64 bit con Linux Mint installata.Come collegare la libreria di runtime C con 'ld'?

Il motivo per cui sono confuso è che, per quanto ne so, invece di collegare il runtime C, gcc copia le cose che ti servono nel tuo programma. Potrei sbagliarti, quindi non esitare a correggermi su questo, per favore.

Quello che ho fatto fino a questo punto è di collegarlo usando gcc. Ciò produce un pasticcio di un codice macchina che non riesco a seguire, anche per un programma di piccole dimensioni come lo scambio rax con rbx, che non è eccezionale per scopi di apprendimento. (Si prega di notare che il programma funziona.)

io non sono sicuro se è rilevante, ma questi sono i comandi che sto usando per compilare e link:

# compilation 
nasm -f elf64 swap.asm 
# gcc 
gcc -o swap swap.o 
# ld, no c runtime 
ld -s -o swap swap.o 

Grazie in anticipo!


Conclusione:

Ora che ho una risposta adeguata alla domanda, qui ci sono alcune cose che vorrei menzionare. Il collegamento glibc dinamicamente può essere eseguito come nella risposta Z boson (per sistemi a 64 bit). Se vuoi farlo staticamente, do follow this link (che sto postando dalla risposta Z boson).

Ecco un articolo che Jester pubblicato, circa how programs start in linux.

Per vedere cosa gcc collega al proprio .o -s, provare questo comando: gcc -v -o swap swap.o. Nota che 'v' sta per 'verbose'.

Inoltre, you should read this se si è interessati al montaggio a 64 bit.

Grazie si per le vostre risposte e utile insight! Fine del discorso

+2

Risposta breve: no. Sfortunatamente la libc include non solo la libreria dinamica, ma una serie di oggetti statici necessari per l'inizializzazione e l'arresto. Se vuoi davvero farlo, usa 'gcc -v' per vedere quali sono le parti necessarie. Potresti essere interessato a questo [articolo fantastico sull'avvio del programma] (http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html). – Jester

+0

'gcc -o swap swap.o' collega il runtime. 'ld -o swap.o' non lo fa. Il collegamento include la copia di parti di grandi dimensioni del runtime sull'eseguibile. Qual è il problema esattamente? –

+0

@Jester Lo esaminerò subito! – mrDudePerson

risposta

4

Ecco un esempio che utilizza libc senza usare GCC.

extern printf 
extern _exit 

section .data 
    hello:  db 'Hello world!',10 

section .text 
    global _start 
_start: 
    xor eax, eax 
    mov edi, hello 
    call printf 
    mov rax, 0  
    jmp _exit 

Compilare e link come questo:

nasm -f elf64 hello.asm 
ld hello.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc -melf_x86_64 

Questo ha funzionato bene finora per me ma per static linkage it's complicated.

+0

Grazie, proverò più tardi. Se funziona, selezionerò questa come risposta corretta :) – mrDudePerson

+0

Sì, funziona! Grazie :) – mrDudePerson

2

Se si desidera chiamare funzioni di libreria semplici come atoi, ma ancora evitare di utilizzare il runtime C, è possibile farlo. (Cioè si scrive _start, piuttosto che solo la scrittura di un main che viene chiamato dopo che un mucchio di codice caldaia-piastra viene eseguito.)

gcc -o swap -nostartfiles swap.o 

Come dicono nei commenti, alcune parti della glibc dipendono costruttori/distruttori eseguito da i file di avvio standard. Probabilmente questo è il caso di stdio (puts/printf/scanf/getchar), e forse di malloc. Molte funzioni sono funzioni "pure" che elaborano solo l'input che viene loro assegnato. sprintf/sscanf potrebbe essere ok da usare.

Ad esempio:

$ cat >exit64.asm <<EOF 
section .text 

extern exit 

global _start 
_start: 

    xor edi, edi 
    jmp exit   ; doesn't return, so optimize like a tail-call 

    ;; or make the syscall directly, if the jmp is commented 
    mov eax, 231 ; exit(0) 
    syscall 

; movl eax, 1  ; 32bit call 
; int 0x80 
EOF 

$ yasm -felf64 exit64.asm && gcc -nostartfiles exit64.o -o exit64-dynamic 
$ nm exit64-dynamic 
0000000000601020 D __bss_start 
0000000000600ec0 d _DYNAMIC 
0000000000601020 D _edata 
0000000000601020 D _end 
       U [email protected]@GLIBC_2.2.5 
0000000000601000 d _GLOBAL_OFFSET_TABLE_ 
00000000004002d0 T _start 
$ ltrace ./exit64-dynamic 
enable_breakpoint pid=11334, addr=0x1, symbol=(null): Input/output error 
exit(0 <no return ...> 
+++ exited (status 0) +++ 
$ strace ... # shows the usual system calls by the runtime dynamic linker 
+0

Sì, grazie, sarà perfetto! :) – mrDudePerson

+0

@mrDudePerson: non dimenticare di "accettare" una risposta che ha risolto il tuo problema. (fare clic sulla casella di controllo sotto le frecce di voto su/giù). Altrimenti la domanda si presenta ancora come senza risposta. –