2013-04-27 12 views
9

È possibile generare funzioni linguaggio assembly dalle funzioni C tramite GCC, in modo che possano essere richiamate da un programma in linguaggio assembly? So che gcc compila il codice da computer C (che può essere facilmente smontato in linguaggio assembly), e so già che è possibile effettuare il inline assembly language functions in C, ma non ho ancora trovato un modo per richiamare le funzioni C dai programmi in linguaggio assembly, che è fondamentalmente l'inverso di questo.Chiamare funzioni C da linguaggio assembly x86

Qui, sto tentando di incorporare una funzione C in un programma di assemblaggio x86. Se l'inlining non è possibile, c'è un altro modo per invocare una funzione C da un programma in linguaggio assembly?

.686p 
.model flat,stdcall 
.stack 2048 

.data 

.code 
start: 

invoke ExitProcess, 0 

printSomething PROC ;now I'm attempting to inline a C function here 
    void printSomething(thingToPrint){ 
     printf("This is a C function that I want to invoke from an assembly language program."); 
     printf("There must be some way to do this - is it possible somehow?"); 
    } 
printSomething ENDP 

end start 
+0

Non ricordo tutti i dettagli, ma è sufficiente compilare i file oggetto e collegarli tra loro. Hai solo bisogno di sapere quali convenzioni di chiamata vengono utilizzate quando si richiama la funzione. –

+1

È possibile aggiungere il codice assembly che mostra ciò che si è provato e indicare come non riesce a compilare o come si comporta male. Sarebbe molto più facile per una risposta indicare il problema. – hyde

+3

Puoi imparare come farlo scrivendo una funzione C che chiama la funzione che vuoi chiamare, la compila in linguaggio assembly ('-S'), e studia i risultati. Ti indicherò anche "psABI", ma non riesco più a trovare una copia. – zwol

risposta

17

Sto andando dalla memoria qui, quindi potrei essere leggermente fuori su un dettaglio o due. Tuttavia, dovrei sperare di essere abbastanza per farti andare nella giusta direzione.

Si sta andando ad avere bisogno di dire al assembler GCC che la vostra routine printSomething() non è definito nel file di assiemi. In "C" si utilizza la parola chiave extern. Per il montaggio è necessario utilizzare .globl.

.globl printSomething 

Se si utilizza un assemblatore diverso rispetto a GCC di, la parola chiave potrebbe essere diverso.

La prossima grande domanda è "come passare gli argomenti"? Questo dipende molto dal processore e dal sistema operativo. Dal momento che il titolo della tua domanda indica x86, assumerò che tu stia utilizzando sia la modalità a 16 o 32 bit e l'ABI standard x86 (a differenza di x86-64, che differisce anche da Windows a Linux). I parametri C vengono passati alla routine chiamata spingendoli nello stack. Sono spinti in pila da destra a sinistra.

Così,

printSomething (arg1, arg2, arg3, arg4); 

si traduce in ...

pushl arg4 
pushl arg3 
pushl arg2 
pushl arg1 
call printSomething 
addl $0x10, %esp 

Si può chiedere se stessi, che cosa è questo

addl $0x10, %esp 

? Abbiamo passato (aka spinto) quattro argomenti a 32 bit alla routine (sullo stack). Sebbene la routine sappia aspettarsi tali argomenti, NON è responsabile di farli fuoriuscire dallo stack. Il chiamante è responsabile per questo. Quindi, dopo che torniamo dalla routine, regoliamo il puntatore dello stack per scartare i quattro argomenti a 32 bit che abbiamo precedentemente inserito nello stack.

Nell'esempio precedente, suppongo che stiamo operando in modalità a 32 bit. Se fosse a 16 bit mode, sarebbe ...

pushw arg4 
pushw arg3 
pushw arg2 
pushw arg1 
call printSomething 
addw $0x8, %sp 

mi rendo conto che nel tuo esempio, printSomething() richiede solo un (1) discussione e nel mio esempio ho usato quattro (4) . Basta regolare il mio esempio come è necessario.

Per le fasi finali, è necessario compilare i file sia il C e il montaggio in file oggetto, collegare i file oggetto e quindi eseguire.

Spero che questo aiuti.

+0

Ora mi chiedo se sia possibile generare effettivamente le procedure di assemblaggio x86 dalle funzioni C usando GCC. Sarebbe possibile convertire tutte le funzioni in un programma C nella funzione equivalente del linguaggio assembly, utilizzando GCC o qualche altro compilatore C? –

+1

@AndersonGreen - Puoi sempre provare a utilizzare l'opzione -S. "gcc -S file.c" convertirà "file.c" in assembly (nominandolo file.s). In alternativa, se hai già il tuo eseguibile, puoi usare "objdump -d exe_file> exe_file.asm" per disassemblare "exe_file" e scaricare il risultato in "exe_file.asm". – Sparky

+0

@Sparky Nella convenzione di procedura x86, ogni funzione ha 'leave' o istruzioni equivalenti prima di tornare al chiamante. Penso che il 'addl $ 0x10,% esp' nel tuo esempio sia ridondante. – StrikeW