The accessing instructions contain load
and load
series. All load
instructions pop off an i32
value as an unsigned integer byte offset. You can see how many bytes the instruction would read or extend. The loaded value is pushed onto the stack.
i32.load8_s
: load 1 byte and sign-extend i8 toi32
i32.load8_u
: load 1 byte and zero-extend i8 toi32
i32.load16_s
: load 2 bytes and sign-extend i16 toi32
i32.load16_u
: load 2 bytes and zero-extend i16 toi32
i32.load
: load 4 bytes asi32
i64.load8_s
: load 1 byte and sign-extend i8 toi64
i64.load8_u
: load 1 byte and zero-extend i8 toi64
i64.load16_s
: load 2 bytes and sign-extend i16 toi64
i64.load16_u
: load 2 bytes and zero-extend i16 toi64
i64.load32_s
: load 4 bytes and sign-extendi32
toi64
i64.load32_u
: load 4 bytes and zero-extendi32
toi64
i64.load
: load 8 bytes asi64
f32.load
: load 4 bytes asf32
f64.load
: load 8 bytes asf64
The following module uses i32.load8_s
read 8 bytes five times.
(module
(import "env" "log" (func $log (param i32)))
(memory (data "Hello"))
(func $main
(local $i i32)
loop
(i32.load8_s (get_local $i))
call $log
(set_local $i
(i32.add
(get_local $i)
(i32.const 1)
)
)
(br_if 0
(i32.ne
(get_local $i)
(i32.const 5)
)
)
end
)
(start $main)
)
The imported $log
function uses String.fromCharCode
to create a string every time so the console will print "Hello"
.
const importObj = {
env: {
log(n) {
console.log(String.fromCharCode(n));
}
}
};
WebAssembly.instantiateStreaming(fetch('program.wasm'), importObj);
If any of the accessed bytes are beyond the current memory size, the access is considered out-of-bounds.
All store
instructions pop off the value you want to save and then an unsigned integer byte offset. For example, if you want to save 72:
(module
(import "env" "log" (func $log (param i32)))
(memory 1)
(func $main
i32.const 0 ;; offset
i32.const 72 ;; the value you want to save
i32.store8
i32.const 0
i32.load8_s
call $log
)
(start $main)
)
The code is not intuitive; however, you can use the style shown below.
(module
(import "env" "log" (func $log (param i32)))
(memory 1)
(func $main
(i32.store8 (i32.const 0) (i32.const 72))
(i32.load8_s (i32.const 0))
call $log
)
(start $main)
)
Store instructions do not produce a value.
i32.store8
: wrapi32
to i8 and store 1 bytei32.store16
: wrapi32
to i16 and store 2 bytesi32.store
: (no conversion) store 4 bytesi64.store8
: wrapi64
to i8 and store 1 bytei64.store16
: wrapi64
to i16 and store 2 bytesi64.store32
: wrapi64
toi32
and store 4 bytesi64.store
: (no conversion) store 8 bytesf32.store
: (no conversion) store 4 bytesf64.store
: (no conversion) store 8 bytes