Call a foreign-language function: Difference between revisions

→‎NASM: rewrote it, the old one made me puke. -.-
m (omit from assembly)
(→‎NASM: rewrote it, the old one made me puke. -.-)
Line 3,050:
===NASM===
{{trans|Wren}}
So yeah. This inits Wrens WMVM in Assembly to call strdup in C. Now PIE(Position independent executable) compliant.
<lang asm>
;; Libc libc stuff..
extern printf
extern exit
extern malloc
extern free
extern fopen
extern fclose
extern fread
extern fseek
extern ftell
extern rewind
 
;; Wren importsstuff..
extern wrenNewVM
extern wrenInterpret
extern wrenFreeVM
extern wrenGetSlotString
extern wrenSetSlowStringwrenSetSlotString
extern wrenInitConfiguration
 
%define WREN_RESULT_SUCCESS 0
;; Our C function
%define WREN_RESULT_COMPILE_ERROR 1
%define WREN_RESULT_RUNTIME_ERROR 2
 
;; Stuff...
extern C_strdup
 
;; time saver 'macros' for PIC(mmm, PIE..)
;; Wren Interpret results
;; These Macros basically end up being exactly what they look
%assign WREN_RESULT_SUCCESS 0
;; like in code, there's very little preprocessing in NASM,
%assign WREN_RESULT_COMPILE_ERROR 1
;; unlike M/UASM's macro systems.(Still more than Gas doe..)
%assign WREN_RESULT_RUNTIME_ERROR 2
%macro xlea 2
lea %1, [rel %2]
%endmacro
 
%macro xcall 1
call [rel %1 wrt ..got]
%endmacro
 
section .bss
wrenConfig resb 84
WrenConfig resb 84 ;; The config struct is 84 bytes(10qwords(8 bytes), 1dword(4 bytes))
WrenVMwrenVM resq 1 ;; wren VM handle
 
section .rodata
;; Messages and shit..
szmsg db "--> Starting and configuring WrenVM",10,0
vm_err_strsznoargs db "--> Returned! anNo error",10,"-->args passed. ErrorSupply number:a %dfilename.",10,0
sznofile db "--> ! Invaild file passed.",10,0
szothererr db "--> ! Wren Error, check script...",10,0
szmod db "main",0
pfmt db "%s",0
szread db "r",0 ;; Why does this have to be a string? Seriously.
 
;; Let this freakshow begin..
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
Line 3,099 ⟶ 3,111:
push rbp
mov rbp, rsp
leasub rdirsp, szmsg16
cmp edi, 1 ;; argc
call printf
jle _main_noargs ;; if(argc <= 1)
lea rdi, WrenConfig
mov rax, qword [rsi+1*8] ;; argv[1] - dun dun dunnnn
call wrenInitConfiguration
leamov raxqword [rbp-8], WrenConfigrax
leaxlea rbxrdi, bindfuncszmsg
xcall printf
mov qword [rax+24], rbx ;; wrenconfig.WrenBindForeignMethodFn
leaxlea rbxrdi, writefnwrenConfig
xcall wrenInitConfiguration
mov qword [rax+40], rbx ;; wrenconfig.WrenWriteFn
leaxlea rbxrax, errfnwrenConfig
xlea rbx, bindfn
mov qword [rax+48], rbx ;; wrenconfig.WrenErrorFn
mov qword [rax+24], rbx ;; wrenconfig.WrenBindForeignFn
lea rdi, WrenConfig
callxlea wrenNewVMrbx, writefn
mov qword [rax+40], rbx ;; wrenconfig.WrenWriteFn
mov [WrenVM], rax
xlea rbx, errfn
lea rdx, c_strdup_wren ;; script
leamov rsiqword [rax+48], mod rbx ;; modulewrenconfig.WrenErrorFn
movxlea rdi, [WrenVM] ;; WrenVM wrenConfig
callxcall wrenInterpretwrenNewVM
mov [rel wrenVM], rax
mov rdi, qword [rbp-8]
call srcread
mov qword [rbp-16], rax ;; char *wrenScript;
mov rdx, qword [rbp-16]
xlea rsi, szmod
mov esi, 0
mov rdi, [rel wrenVM]
xcall wrenInterpret
cmp rax, WREN_RESULT_SUCCESS
jg _main_noargs
jg _wrenvm_err ;; if > RESULT_SUCCESS = error.
jmp _exit ;; Time to gtfo.
 
jmp _main_exit ;; Let's gtfo of dodge.
_wrenvm_err:
mov rsi, rax
_main_noargs:
lea rdi, vm_err_str
callxlea printfrdi, sznoargs
xcall printf
 
;; At this point we should free the mem but
_exit:
;; the program ends so who gives a ....
mov rdi, [WrenVM]
_main_exit:
call wrenFreeVM
movadd raxrsp, 016
pop rbp
xor rdi, rdi
callxcall exit
ret
 
;; We only care about the file name once, So.. No keepy keepy.
;;Callback functions for the WrenVM
srcread:
;; writefn(rdi, rsi) - WrenVM isn't used so just overwrite it.
push rbp
mov rbp, rsp
sub rsp, 32
xlea rsi,szread
xcall fopen
cmp rax, 0
jle _srcread_nofile
mov qword [rbp-8], rax ;; file handle.
mov edx, 2 ;; SEEK_END
mov esi, 0
mov rdi, qword [rbp-8]
xcall fseek
mov rdi, qword [rbp-8]
xcall ftell
mov qword [rbp-16], rax
mov rdi, qword [rbp-8]
xcall rewind
mov rax, qword [rbp-16]
add rax, 1
mov rdi, rax
xcall malloc
mov qword [rbp-24], rax
mov rcx, qword [rbp-8] ;; file handle
mov rdx, qword [rbp-16] ;; size
mov esi, 1
mov rdi, qword [rbp-24] ;; buffer
xcall fread
mov rdi, qword [rbp-8]
xcall fclose
mov rcx, qword [rbp-16]
mov rax, qword [rbp-24]
add rax, rcx
mov byte [rax], 0
jmp _srcread_exit
 
_srcread_nofile:
xlea rdi, sznofile
xcall printf
 
_srcread_exit:
mov rax, qword [rbp-24]
add rsp, 32
pop rbp
ret
 
;; Just prints whatever's given to it's one argument.
writefn:
push rbp
mov rbp, rsp
leaxlea rdi, msgpfmt
callxcall printf
pop rbp
ret
 
;; Just print generic message and return the error number
errfn:
push rbp
mov rbp, rsp
movxlea rdi, vm_err_strszothererr
callxcall printf
mov rax, 0
pop rbp
ret
 
;; Still to lazy to do those if checks... -.-
bindfunc:
;; I'll do it properly one day, I promise. :]
push rbp
bindfn:
mov rbp, rsp
push rbp
lea rax, C_strdup
mov rbp, pop rbprsp
xlea rax, retC_strdup
pop rbp
ret
 
</lang>
strdup.wren
<lang wren>
class C {
foreign static strdup(s)
}
var s = "Goodbye, World!"
System.print(C.strdup(s))
</lang>
strdup.c
<lang c>
void free( void* ptr );
Line 3,180 ⟶ 3,257:
<pre>
--> Starting and configuring WrenVM
--> HelloGoodbye, World!
</pre>