Call a foreign-language function: Difference between revisions

no edit summary
No edit summary
Line 2,744:
Hello World!
</pre>
 
=={{header|X86-64 Assembly}}==
===UASM 2.52===
Calling C functions in Assembly is trivial at best. It's not anymore complicated than using them in C itself. Strdup for example..
<lang asm>
option casemap:none
 
strdup proto :qword
printf proto :qword, :vararg
exit proto :dword
 
.data
bstr db "String 1",0
 
.data?
buff dq ?
 
.code
main proc
invoke printf, CSTR("Copying %s to buff with strdup using invoke....",10), addr bstr
invoke strdup, addr bstr
mov buff, rax
invoke printf, CSTR("buff now = %s",10), buff
invoke exit, 0
ret
main endp
end
;Now, we could target a specific ABI by assigning the call values to the registers like
;.code
;main proc
; lea rdi, bstr
; call strdup
; mov buff, rax
;main endp
;end
</lang>
but that's not very fun. So let's run some lua script insted.
<lang asm>
option casemap:none
option literals:on
 
windows64 equ 1
linux64 equ 3
 
ifndef __LUA_CLASS__
__LUA_CLASS__ equ 1
LUA_OK equ 0
 
if @Platform eq windows64
option dllimport:<kernel32>
GetProcessHeap proto
ExitProcess proto :dword
HeapAlloc proto :qword, :dword, :qword
HeapFree proto :qword, :dword, :qword
option dllimport:none
exit equ ExitProcess
elseif @Platform eq linux64
malloc proto SYSTEMV :qword
free proto SYSTEMV :qword
endif
 
printf proto :qword, :vararg
exit proto :dword
;; Lua.h funcs
luaL_newstate proto ;; lua_State *luaL_newstate();
lua_gettop proto :qword ;; int lua_getopt(lua_State *L);
lua_close proto :qword ;; void lua_close(lua_State *L);
luaL_openlibs proto :qword ;; int luaL_openlibs(lua_State *L);
lua_settop proto :qword, :dword ;; int lua_setopt(lua_State *L, int idx)
luaL_loadstring proto :qword, :qword ;; int luaL_loadstring(lua_state *L, char *string);
lua_pcallk proto :qword, :dword, :dword, :dword, :dword, :dword
 
CLASS lua_class
CMETHOD runstr
ENDMETHODS
lua_state qword 0
ENDCLASS
 
METHOD lua_class, Init, <VOIDARG>, <>
mov rbx, thisPtr
assume rbx:ptr lua_class
invoke luaL_newstate
mov [rbx].lua_state, rax
invoke luaL_openlibs, [rbx].lua_state
.if rax != LUA_OK
invoke printf, CSTR("---> Lua failed to open libs",10)
jmp _ext
.endif
 
_ext:
mov rax, rbx
assume rbx:nothing
ret
ENDMETHOD
 
METHOD lua_class, runstr, <VOIDARG>, <>, s:qword
local tmp:qword
 
mov rbx, thisPtr
assume rbx:ptr lua_class
mov rax, s
mov tmp, rax
invoke luaL_loadstring, [rbx].lua_state, tmp
invoke lua_pcallk, [rbx].lua_state, 0, 0, 0, 0, 0
.if rax != LUA_OK
invoke printf, CSTR("--> luaL_pcallk failed with %i",10), rax
.else
invoke lua_gettop, [rbx].lua_state
not eax
invoke lua_settop, [rbx].lua_state, eax
.endif
mov rax, 0
assume rbx:nothing
ret
ENDMETHOD
 
METHOD lua_class, Destroy, <VOIDARG>, <>
mov rbx, thisPtr
assume rbx:ptr lua_class
.if [rbx].lua_state != 0
invoke lua_close, [rbx].lua_state
.endif
assume rbx:nothing
ret
ENDMETHOD
 
endif ;__LUA_CLASS__
 
.code
main proc
local lvm:ptr lua_class
invoke printf, CSTR("-> Attempting to init Lua...",10)
mov lvm, _NEW(lua_class)
invoke printf, CSTR("-> Lua started, Running first test..",10)
lvm->runstr(CSTR("print('Goodbye, world from Lua..')"))
.if rax != LUA_OK
invoke printf, CSTR("-> Runstring failed, exiting...",10)
jmp _ext
.endif
 
_ext:
_DELETE(lvm)
mov rax, 0
invoke exit, 0
main endp
 
end
</lang>
{{out}}
<pre>
-> Attempting to init Lua...
-> Lua started, Running first test..
Goodbye, world from Lua..
</pre>
When I stop being lazy and/or drunk, I'll update the class to run a lua script file...
 
=={{header|zkl}}==