Ask coding questions

← Back to all posts
How should I pass control to another Wasm module?
h
programmeruser (595)

How should I pass control to another wasm module (like jmp) while preserving the current state e.g. the stack?

Answered by xxpertHacker (930) [earned 5 cycles]
View Answer
Comments
hotnewtop
xxpertHacker (930)

As modules do not have "control," only functions do, and you want to maintain the stack's state, I presume that you would want to be using function calls?

programmeruser (595)

@xxpertHacker
Are dynamic imports possible in wasm, and how would I handle a unknown function signature? In regular processor code there is no such thing as a label, only addresses so I wouldn't have to worry about this.

xxpertHacker (930)

@programmeruser Dynamic imports are not possible, but dynamic calls are.

call_indirect and function pointers into tables.

If you attempt to call a function with a mis-matched signature, then the code traps immediately.

You should pass around a (table funcref), between the modules, use table.set, and table.get and call via function pointers to the table.

And if you need to replicate a register-like structure, you can store into globals, call the function, and then read from them in the callee.

xxpertHacker (930)

Did you ever get the idea working? If so, how did it work out?

programmeruser (595)

@xxpertHacker I got stuck on how to expose features to programs (e.g. jmp, things that would normally be handled by interrupts). I only got to a VGA textmode clone and a "BIOS"

xxpertHacker (930)

@programmeruser Well... idk.

Interrupts have a payload, which the OS may or may not have a registered handler for, and is called if present upon the interrupt.

The payload could be represented as a usize, and used to access an array of functions... but that sounds wrong.

Why can't they just be imported functions?

Syscalls are OS functions, just forget about the interrupt overhead, and call the function.

Example:
Linux pipe is the following:

int pipe(int pipefd[2]);

This could be imported as

(import "syscall" "pipe" (func $syscall::pipe (param i32) (result i32)))

As for how it would be exported to the module, that depends on the Wasm VM.