Hello World in WebAssembly

Michael Bebenita
2 min readMar 9, 2017

--

So you’ve heard the great news about WebAssembly (now shipping in Firefox 52) and can’t wait to try it out. Where do you start? Well, I would start with “Hello World” of course.

Fire up your favorite editor and write the following WebAssembly program in JavaScript:

var buffer = new Uint8Array([0,97,115,109,1,0,0,0,1,133,128,128,128,0,1,96,0,1,127,3,130,128,128,128,0,1,0,4,132,128,128,128,0,1,112,0,0,5,131,128,128,128,0,1,0,1,6,129,128,128,128,0,0,7,146,128,128,128,0,2,6,109,101,109,111,114,121,2,0,5,104,101,108,108,111,0,0,10,138,128,128,128,0,1,132,128,128,128,0,0,65,16,11,11,146,128,128,128,0,1,0,65,16,11,12,72,101,108,108,111,32,87,111,114,108,100,0]);var m = new WebAssembly.Instance(new WebAssembly.Module(buffer));
var h = new Uint8Array(m.exports.memory.buffer);
var p = m.exports.hello();
function utf8ToString(h, p) {
let s = "";
for (i = p; h[i]; i++) {
s += String.fromCharCode(h[i]);
}
return s;
}
console.log(utf8ToString(h, p));

Magic. What’s going on here? Let’s take a look at what is in the buffer array.

(module
(type $type0 (func (result i32)))
(table 0 anyfunc)
(memory 1)
(export "memory" memory)
(export "hello" $func0)
(func $func0 (result i32)
i32.const 16
)
(data (i32.const 16)
"Hello World\00"
)
)

Here is what that binary blob looks like in the WebAssembly text format. Notice there’s an (export “hello” $func0) statement which exports a function called$func0. When we instantiate the WebAssembly module, this function is made available through the m.exports.hello property. The function returns the address of the "Hello World” string which lives somewhere in the module’s data section. To read its contents, we’ll need to poke into the module’s memory (notice that memory is also conveniently exported):

let h = new Uint8Array(m.exports.memory.buffer);

and then write a little utility to convert UTF8 strings to JavaScript strings:

function utf8ToString(h, p) {
let s = "";
for (i = p; h[i]; i++) {
s += String.fromCharCode(h[i]);
}
return s;
}
let p = m.exports.hello();
console.log(utf8ToString(h, p));

and, we’re done. If you’re feeling adventurous and want to do some low level hacking, try changing the last few bytes of the buffer which currently looks like this:

[ …, 72,101,108,108,111,32,87,111,114,108,100,0]

to

[…, 72,101,108,108,111,0,87,111,114,108,100,0]

and see what happens. Here’s a fiddle where you can play with it, and the C program if you were curious:

char * hello() {
return "Hello World";
}

--

--