如何调用 C extern 函数并获取 return 结构?
How to call C extern function and get return struct?
我在 token.c
中定义了一个外部函数和一个 struct
:
#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] new token: start [5] length [10]
start: 5
length: 0
我缺少什么来获得开始和长度?输出验证 C 中的 extern 函数被调用并且值被推送到函数中。
As I stated in a comment.
it would be far better to pass a pointer to
an instance of struct token
rather than the current code.
The following follows the current code.
but remember all those hidden calls to memcpy()
and the hidden ram allocation
otherfile.h 包含
#ifndef OTHER_FILE_H
#define OTHER_FILE_H
struct token
{
int start;
int length;
};
struct token get_token( int, int );
#endif // OTHER_FILE_H
在文件中 otherfile.c
#include <stdio.h>
#include "otherfile.h"
struct token get_token( int tokenStart, int tokenLength )
{
printf("[C] new token: start [%d] length [%d]\n\n", s, l);
struct token m_T = {0,0};
m_T.start = tokenStart;
m_T.length = tokenLength;
return m_T;
}
在文件中 token.c
#include <stdio.h>
#include "otherfile.h"
...
struct token myToken = {0,0};
myToken = get_token( tokenStart, tokenLength );
...
我认为问题出在您的 .bss
部分:
SECTION .bss ; uninitialized data
tkn: resd 1
在这里,您为令牌预留了一个 dword
(一个整数值的内存)内存。但是,在您的 C 代码中,您将令牌结构定义为具有 2 int
s(start
和 length
)或 2 dword
s 的内存。这意味着您只能写入令牌结构的一部分 (start
),并且成员 length
被视为不存在。您的问题可能可以通过简单地将 tkn
定义为
来解决
tkn: resd 2
或
tkn: resq 1 ;; 1 QWORD == 2 DWORDs
希望对您有所帮助 ;)
我决定不是一次一个标记,而是分配一个缓冲区并填充它:确定需要多少标记,malloc
缓冲区,调用 get_tokens
并传入指向缓冲区的指针和令牌数。
get_tokens
方法填充缓冲区和 returns 创建的令牌计数。
程序集然后迭代令牌缓冲区并显示每个令牌的值 - start
和 length
。
token.c:
#include <stdio.h>
typedef struct token {
int start;
int length;
} t;
extern int get_tokens(t*, int);
extern int token_size();
/*
p_t: pointer to allocated buffer
num: number of tokens with which to fill buffer
*/
int get_tokens(t* p_t, int num) {
printf("[C] create %d tokens: %d bytes\n", num, token_size() * num);
int idx = 0;
while (idx < num) {
// values are arbitrary for testing purposes
t tkn = {idx, idx * 10};
p_t[idx] = tkn;
printf("[C] [%d] start: %d; len: %d\n", idx, tkn.start, tkn.length);
++idx;
}
return idx;
}
int token_size() {
return sizeof(t);
}
make_tokens.asm:
SECTION .data ; initialized data
endl: db 10, 0
mszt: db "token size: %d bytes", 10, 0
tk_info: db "[%d]: s[%d] l[%d]", 10, 0
mlen db "length: %d", 10, 0
mstt: db "start: %d", 10, 0
mend: db 10, "*** END ***", 10, 0
mt1 db "malloc space for 3 tokens: %d bytes", 10, 0
mty db 10, "success", 10, 0
mtn db 10, "fail", 10, 0
SECTION .text ; code
extern _get_tokens
extern _token_size
extern _free
extern _malloc
extern _printf
global _main
_main:
; stash base stack pointer
push ebp
mov ebp, esp
; get token size
call _token_size
mov [tsz], eax
push DWORD [tsz]
push DWORD mszt
call _printf
add esp, 8
mov eax, [tsz]
mov edx, 3
mul edx
mov [tbsz], eax
push DWORD [tbsz]
push DWORD mt1
call _printf
add esp, 8
push DWORD [tbsz] ; malloc 3 tokens
call _malloc
mov [tkn_buf], eax
add esp, 4
mov ecx, 3 ; 3 tokens
push DWORD ecx
push DWORD [tkn_buf]
call _get_tokens
add esp, 8
cmp eax, 3
je .yes
.no:
push DWORD mtn
call _printf
add esp, 4
jmp .end
.yes:
push DWORD mty
call _printf
add esp, 4
mov ecx, 0
mov ebx, [tkn_buf]
.loopTokens:
mov eax, [tsz] ; determine next token
mul ecx ; start location => eax
mov edi, ecx ; preserve counter
push DWORD [ebx + eax + 4] ; length
push DWORD [ebx + eax] ; start
push DWORD ecx
push DWORD tk_info
call _printf
add esp, 16
mov ecx, edi
inc ecx
cmp ecx, 3
jl .loopTokens
.end:
push DWORD [tkn_buf]
call _free
push DWORD mend
call _printf
; restore base stack pointer
mov esp, ebp
pop ebp
SECTION .bss ; uninitialized data
tkn_buf: resd 1
tbsz: resd 1
tsz: resd 1
...结果输出:
token size: 8 bytes
malloc space for 3 tokens: 24 bytes
[C] create 3 tokens: 24 bytes
[C] [0] start: 0; len: 0
[C] [1] start: 1; len: 10
[C] [2] start: 2; len: 20
success
[0]: s[0] l[0]
[1]: s[1] l[10]
[2]: s[2] l[20]
我在 token.c
中定义了一个外部函数和一个 struct
:
#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] new token: start [5] length [10]
start: 5
length: 0
我缺少什么来获得开始和长度?输出验证 C 中的 extern 函数被调用并且值被推送到函数中。
As I stated in a comment.
it would be far better to pass a pointer to
an instance of struct token
rather than the current code.
The following follows the current code.
but remember all those hidden calls to memcpy()
and the hidden ram allocation
otherfile.h 包含
#ifndef OTHER_FILE_H
#define OTHER_FILE_H
struct token
{
int start;
int length;
};
struct token get_token( int, int );
#endif // OTHER_FILE_H
在文件中 otherfile.c
#include <stdio.h>
#include "otherfile.h"
struct token get_token( int tokenStart, int tokenLength )
{
printf("[C] new token: start [%d] length [%d]\n\n", s, l);
struct token m_T = {0,0};
m_T.start = tokenStart;
m_T.length = tokenLength;
return m_T;
}
在文件中 token.c
#include <stdio.h>
#include "otherfile.h"
...
struct token myToken = {0,0};
myToken = get_token( tokenStart, tokenLength );
...
我认为问题出在您的 .bss
部分:
SECTION .bss ; uninitialized data
tkn: resd 1
在这里,您为令牌预留了一个 dword
(一个整数值的内存)内存。但是,在您的 C 代码中,您将令牌结构定义为具有 2 int
s(start
和 length
)或 2 dword
s 的内存。这意味着您只能写入令牌结构的一部分 (start
),并且成员 length
被视为不存在。您的问题可能可以通过简单地将 tkn
定义为
tkn: resd 2
或
tkn: resq 1 ;; 1 QWORD == 2 DWORDs
希望对您有所帮助 ;)
我决定不是一次一个标记,而是分配一个缓冲区并填充它:确定需要多少标记,malloc
缓冲区,调用 get_tokens
并传入指向缓冲区的指针和令牌数。
get_tokens
方法填充缓冲区和 returns 创建的令牌计数。
程序集然后迭代令牌缓冲区并显示每个令牌的值 - start
和 length
。
token.c:
#include <stdio.h>
typedef struct token {
int start;
int length;
} t;
extern int get_tokens(t*, int);
extern int token_size();
/*
p_t: pointer to allocated buffer
num: number of tokens with which to fill buffer
*/
int get_tokens(t* p_t, int num) {
printf("[C] create %d tokens: %d bytes\n", num, token_size() * num);
int idx = 0;
while (idx < num) {
// values are arbitrary for testing purposes
t tkn = {idx, idx * 10};
p_t[idx] = tkn;
printf("[C] [%d] start: %d; len: %d\n", idx, tkn.start, tkn.length);
++idx;
}
return idx;
}
int token_size() {
return sizeof(t);
}
make_tokens.asm:
SECTION .data ; initialized data
endl: db 10, 0
mszt: db "token size: %d bytes", 10, 0
tk_info: db "[%d]: s[%d] l[%d]", 10, 0
mlen db "length: %d", 10, 0
mstt: db "start: %d", 10, 0
mend: db 10, "*** END ***", 10, 0
mt1 db "malloc space for 3 tokens: %d bytes", 10, 0
mty db 10, "success", 10, 0
mtn db 10, "fail", 10, 0
SECTION .text ; code
extern _get_tokens
extern _token_size
extern _free
extern _malloc
extern _printf
global _main
_main:
; stash base stack pointer
push ebp
mov ebp, esp
; get token size
call _token_size
mov [tsz], eax
push DWORD [tsz]
push DWORD mszt
call _printf
add esp, 8
mov eax, [tsz]
mov edx, 3
mul edx
mov [tbsz], eax
push DWORD [tbsz]
push DWORD mt1
call _printf
add esp, 8
push DWORD [tbsz] ; malloc 3 tokens
call _malloc
mov [tkn_buf], eax
add esp, 4
mov ecx, 3 ; 3 tokens
push DWORD ecx
push DWORD [tkn_buf]
call _get_tokens
add esp, 8
cmp eax, 3
je .yes
.no:
push DWORD mtn
call _printf
add esp, 4
jmp .end
.yes:
push DWORD mty
call _printf
add esp, 4
mov ecx, 0
mov ebx, [tkn_buf]
.loopTokens:
mov eax, [tsz] ; determine next token
mul ecx ; start location => eax
mov edi, ecx ; preserve counter
push DWORD [ebx + eax + 4] ; length
push DWORD [ebx + eax] ; start
push DWORD ecx
push DWORD tk_info
call _printf
add esp, 16
mov ecx, edi
inc ecx
cmp ecx, 3
jl .loopTokens
.end:
push DWORD [tkn_buf]
call _free
push DWORD mend
call _printf
; restore base stack pointer
mov esp, ebp
pop ebp
SECTION .bss ; uninitialized data
tkn_buf: resd 1
tbsz: resd 1
tsz: resd 1
...结果输出:
token size: 8 bytes
malloc space for 3 tokens: 24 bytes
[C] create 3 tokens: 24 bytes
[C] [0] start: 0; len: 0
[C] [1] start: 1; len: 10
[C] [2] start: 2; len: 20success
[0]: s[0] l[0]
[1]: s[1] l[10]
[2]: s[2] l[20]