devo una funzione extern ed una struct
definito token.c
:Come chiamare la funzione C extern e ottenere la struttura di ritorno?
#include "stdio.h"
typedef struct token {
int start;
int length;
} t;
extern t get_token(int, int);
t get_token(int s, int l) {
printf("[C] new token: start [%d] length [%d]\n\n", s, l);
t m_T = {};
m_T.start = s;
m_T.length = l;
return m_T;
}
... in modo che posso chiamare _get_token
dal mio assemblaggio e ottenere un nuovo token. In make_token.asm ho il seguente:
SECTION .data ; initialized data
mtkn: db "call: token(%d, %d)", 10, 0
mlen db "length: %d", 10, 0
mstt: db "start: %d", 10, 0
mend: db 10, "*** END ***", 10, 0
SECTION .text ; code
extern _get_token
extern _printf
global _main
_main:
; stash base stack pointer
push ebp
mov ebp, esp
mov eax, 5
mov ebx, 10
push ebx ; length
push eax ; start
call _get_token ; get a token
mov [tkn], eax
add esp, 8
; test token properties
push DWORD [tkn]
push mstt
call _printf
push DWORD [tkn + 4]
push mlen
call _printf
add esp, 16
.end:
push DWORD mend
call _printf
; restore base stack pointer
mov esp, ebp
pop ebp
SECTION .bss ; uninitialized data
tkn: resd 1
Il risultato è:
[C] nuovo token: start [5] lunghezza [10]
inizio: 5
lunghezza : 0
Cosa mi manca per ottenere sia l'inizio che la lunghezza? L'output verifica che la funzione extern in C venga richiamata e che i valori vengano inseriti nella funzione.
Se ho letto [questa tabella] (http://en.wikipedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions) in modo corretto rispetto seconda metà della vostra risposta dovrebbe essere in EDX - "ritorno POD valori 33-64 bit le dimensioni vengono restituite tramite i registri EAX: EDX. " – zch
1) non digitare le definizioni delle struct. 2) poiché quella struttura è dichiarata in un file diverso, la definizione dovrebbe essere in un file di intestazione, che entrambi i file di origine # includono. 3) il riferimento a una funzione esterna non viene eseguito tramite extern. piuttosto in un file di intestazione comune, incluso in entrambi i file di origine in cui è dichiarata la funzione e nel file locale tramite #include. il file di intestazione avrebbe il prototipo, il linker gestirà il resto. 4) l'ordine di ricerca per i file #include dipende da "< ...>" o "" ... "'è utilizzato. le intestazioni di sistema devono sempre utilizzare "<' and '>" – user3629249
questa riga: "return m_T;" non funzionerà correttamente, perché quando la funzione termina, tutto nello stack è 'perso', quindi restituire un elemento che è in pila è un comportamento indefinito. Tuttavia, poiché viene restituita la struttura completa effettiva anziché un puntatore, il compilatore invocherà memcpy() per copiare la struct in un'area di memoria "nascosta" (che non può essere utilizzata per nient'altro) quindi richiamare memcpy() di nuovo in copia dall'area di memoria nascosta alla variabile dei chiamanti. Molto meglio passare un terzo parametro che è un puntatore all'istanza del chiamante della struct e usare quel puntatore – user3629249