У меня есть Экстерн функция и struct
определенных в token.c
:Как вызвать функцию C extern и получить структуру возврата?
#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;
}
... так что я могу назвать _get_token
из моей сборки и получить новый маркер. В make_token.asm У меня есть следующие:
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
Выход:
[C], новый маркер: начать [5] длина [10]
старт: 5
длина : 0
Что мне не хватает, чтобы получить как начало, так и длину? Вывод проверяет, что внешняя функция в C вызывается, а значения вставляются в функцию.
Если я читал [эту таблицу] (http://en.wikipedia.org/wiki/X86_calling_conventions#List_of_x86_calling_conventions) правильно, чем вторая половина вашего ответа должен быть в EDX - «возвращение POD значения 33-64 бита в размер возвращается через регистры EAX: EDX ». – zch
1) не определяют определения типа typedef. 2) поскольку эта структура объявлена в другом файле, определение должно быть в файле заголовка, так что оба исходных файла #include. 3) ссылка на внешнюю функцию не выполняется через extern. скорее в общем заголовочном файле, который включен как в исходный файл, где объявлена функция, так и в локальный файл через #include. файл заголовка будет иметь прототип, компоновщик обрабатывает остальные. 4) порядок поиска файлов #include зависит от того, что используется '< ...>' или '"..."'. системные заголовки всегда должны использовать '<' and '>' – user3629249
: 'return m_T;' не будет работать корректно, потому что, когда функция выходит, что-либо в стеке «потеряно», поэтому возврат элемента, находящегося в стеке, является неопределенным поведением. Однако, поскольку возвращаемая фактическая полная структура, а не указатель, компилятор будет вызывать memcpy() для копирования структуры в «скрытую» область памяти (которую нельзя использовать ни для чего другого), а затем снова вызвать memcpy() копировать из скрытой области памяти в переменную вызывающих. Гораздо лучше передать третий параметр, который является указателем на экземпляр вызывающих объектов структуры, и использовать этот указатель – user3629249