Call a foreign-language function: Difference between revisions
Content added Content deleted
m (→UASM 2.52) |
(→{{header|X86-64 Assembly}}: (N)asm calls Wren calls C. o.O) |
||
Line 3,047: | Line 3,047: | ||
---> Lua calc: 1342 + 1551 = 2893 |
---> Lua calc: 1342 + 1551 = 2893 |
||
-> Return from lua func: 2893 |
-> Return from lua func: 2893 |
||
</pre> |
|||
===NASM=== |
|||
{{trans|Wren}} |
|||
So yeah. This inits Wrens WM in Assembly to call strdup in C. |
|||
<lang asm> |
|||
;; Libc stuff.. |
|||
extern printf |
|||
extern exit |
|||
;; Wren imports |
|||
extern wrenNewVM |
|||
extern wrenInterpret |
|||
extern wrenFreeVM |
|||
extern wrenGetSlotString |
|||
extern wrenSetSlowString |
|||
extern wrenInitConfiguration |
|||
;; Our C function |
|||
extern C_strdup |
|||
;; Wren Interpret results |
|||
%assign WREN_RESULT_SUCCESS 0 |
|||
%assign WREN_RESULT_COMPILE_ERROR 1 |
|||
%assign WREN_RESULT_RUNTIME_ERROR 2 |
|||
section .bss |
|||
WrenConfig resb 84 ;; The config struct is 84 bytes(10qwords(8 bytes), 1dword(4 bytes)) |
|||
WrenVM resq 1 ;; wren VM handle |
|||
section .rodata |
|||
;; Messages and shit.. |
|||
szmsg db "--> Starting and configuring WrenVM",10,0 |
|||
vm_err_str db "--> Returned an error",10,"--> Error number: %d",10,0 |
|||
mod db "main",0 |
|||
msg db "--> %s",0 |
|||
;; Hard coded wren script.. |
|||
;; If you care that much, write a filereader yaself T_T |
|||
c_strdup_wren db 'class C {',10 |
|||
db ' foreign static strdup(s)',10 |
|||
db '}',10 |
|||
db 'var s = "Hello World!"',10 |
|||
db 'System.print(C.strdup(s))',10 |
|||
;; Let this freakshow begin... |
|||
section .text |
|||
global main |
|||
main: |
|||
push rbp |
|||
mov rbp, rsp |
|||
lea rdi, szmsg |
|||
call printf |
|||
lea rdi, WrenConfig |
|||
call wrenInitConfiguration |
|||
lea rax, WrenConfig |
|||
lea rbx, bindfunc |
|||
mov qword [rax+24], rbx ;; wrenconfig.WrenBindForeignMethodFn |
|||
lea rbx, writefn |
|||
mov qword [rax+40], rbx ;; wrenconfig.WrenWriteFn |
|||
lea rbx, errfn |
|||
mov qword [rax+48], rbx ;; wrenconfig.WrenErrorFn |
|||
lea rdi, WrenConfig |
|||
call wrenNewVM |
|||
mov [WrenVM], rax |
|||
lea rdx, c_strdup_wren ;; script |
|||
lea rsi, mod ;; module |
|||
mov rdi, [WrenVM] ;; WrenVM |
|||
call wrenInterpret |
|||
cmp rax, WREN_RESULT_SUCCESS |
|||
jg _wrenvm_err ;; if > RESULT_SUCCESS = error. |
|||
jmp _exit ;; Time to gtfo. |
|||
_wrenvm_err: |
|||
mov rsi, rax |
|||
lea rdi, vm_err_str |
|||
call printf |
|||
_exit: |
|||
mov rdi, [WrenVM] |
|||
call wrenFreeVM |
|||
mov rax, 0 |
|||
pop rbp |
|||
xor rdi, rdi |
|||
call exit |
|||
ret |
|||
;;Callback functions for the WrenVM |
|||
;; writefn(rdi, rsi) - WrenVM isn't used so just overwrite it. |
|||
writefn: |
|||
push rbp |
|||
mov rbp, rsp |
|||
lea rdi, msg |
|||
call printf |
|||
pop rbp |
|||
ret |
|||
;; Just print generic message and return the error number |
|||
errfn: |
|||
push rbp |
|||
mov rbp, rsp |
|||
mov rdi, vm_err_str |
|||
call printf |
|||
mov rax, 0 |
|||
pop rbp |
|||
ret |
|||
;; Just stored all the arguments on the stack just in case... |
|||
;; Honestly, if we ignore the module comparison this could be done like |
|||
;; bindfunc: |
|||
;; push rbp |
|||
;; mov rbp, rsp |
|||
;; lea rax, C_strdup |
|||
;; pop rsp |
|||
;; ret |
|||
bindfunc: |
|||
push rbp |
|||
mov rbp, rsp |
|||
sub rsp, (8*6) ;; make some space on the stack to store our arguments. |
|||
mov [rsp+32], rdi ;; WrenVM *vm - not used, Saved for consistancy. |
|||
mov [rsp+24], rsi ;; const char *module |
|||
mov [rsp+16], rdx ;; const char *className - not used, to lazy. |
|||
mov [rsp+8], rcx ;; bool isStatic - not used, to lazy. |
|||
mov [rsp+0], r8 ;; const char *signature - not used, still to lazy. |
|||
mov rdi, [rsp+24] |
|||
call strlen |
|||
cmp rax, 0 |
|||
jle _bf_fail |
|||
mov ecx, eax |
|||
lea rsi, mod |
|||
mov rdi, [rsp+24] |
|||
call strcmp |
|||
cmp eax, 0 |
|||
jne _bf_fail |
|||
lea rax, C_strdup |
|||
jmp _bf_exit |
|||
_bf_fail: |
|||
mov rax, 1 |
|||
_bf_exit: |
|||
add rsp, (8*6) |
|||
pop rbp |
|||
ret |
|||
;; strlen(rdi) - str1 - returns in eax |
|||
strlen: |
|||
push rbp |
|||
mov rbp, rsp |
|||
mov rax,-1 |
|||
_1: |
|||
inc eax |
|||
cmp byte [rdi+rax], 0 |
|||
jne _1 |
|||
pop rbp |
|||
ret |
|||
;;strcmp(rdi, rsi, ecx) str1, str2, maxlen |
|||
strcmp: |
|||
push rbp |
|||
mov rbp, rsp |
|||
repe cmpsb |
|||
jne _false |
|||
mov rax, 0 |
|||
jmp _true |
|||
_false: |
|||
mov rax, 1 |
|||
_true: |
|||
pop rbp |
|||
ret |
|||
</lang> |
|||
<lang c> |
|||
void free( void* ptr ); |
|||
char * strdup( const char *str1 ); |
|||
typedef struct WrenVM WrenVM; |
|||
const char* wrenGetSlotString(WrenVM* vm, int slot); |
|||
void wrenSetSlotString(WrenVM* vm, int slot, const char* text); |
|||
void C_strdup(WrenVM* vm) { |
|||
const char *s = wrenGetSlotString(vm, 1); |
|||
char *t = strdup(s); |
|||
wrenSetSlotString(vm, 0, t); |
|||
free(t); |
|||
} |
|||
</lang> |
|||
{{out}} |
|||
<pre> |
|||
--> Starting and configuring WrenVM |
|||
--> Hello World! |
|||
</pre> |
</pre> |
||