I have an extern function and a struct
defined in token.c
:
#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;
}
... so that I can call _get_token
from my assembly and get a new token. In make_token.asm I have the following:
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
The output is:
[C] new token: start [5] length [10]
start: 5
length: 0
What am I missing to get both start and length? The output verifies that the extern function in C is getting called and the values are pushed into the function.
I decided instead of a single token at a time, that I should allocate a buffer and fill it: determine how many tokens are required, malloc
the buffer, call get_tokens
and pass in the pointer to the buffer and number of tokens.
The get_tokens
method fills the buffer and returns a count of tokens created.
The assembly then iterates the token buffer and displays the values - start
and length
- for each token.
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
...and the resulting output:
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]