Arithmetic and Comparisons
WebAssembly provides a rich set of arithmetic and comparison instructions. Each instruction is typed — you always know whether you are working with integers or floats, and for integers, whether the operation is signed or unsigned.
Integer arithmetic
Section titled “Integer arithmetic”The four basic operations for i32 are i32.add, i32.sub, i32.mul, and division. All pop two operands and push one result:
(module (func (export "add") (param $a i32) (param $b i32) (result i32) local.get $a local.get $b i32.add) (func (export "sub") (param $a i32) (param $b i32) (result i32) local.get $a local.get $b i32.sub) (func (export "mul") (param $a i32) (param $b i32) (result i32) local.get $a local.get $b i32.mul))The same instructions exist for i64: i64.add, i64.sub, i64.mul.
Signed vs unsigned division
Section titled “Signed vs unsigned division”Division is where integer types reveal their complexity. An i32 is just 32 bits — the bits themselves carry no sign information. The instruction decides whether to interpret those bits as a two’s-complement signed integer or as an unsigned integer:
(module ;; signed: -7 / 2 = -3 (rounds toward zero) (func (export "divSigned") (param $a i32) (param $b i32) (result i32) local.get $a local.get $b i32.div_s)
;; unsigned: the same bit pattern as -7 (0xFFFFFFF9) / 2 = 2147483644 (func (export "divUnsigned") (param $a i32) (param $b i32) (result i32) local.get $a local.get $b i32.div_u))Similarly i32.rem_s and i32.rem_u give signed and unsigned remainder.
Float arithmetic
Section titled “Float arithmetic”Float instructions mirror integer ones, but the type prefix changes:
(module (func (export "fadd") (param $a f64) (param $b f64) (result f64) local.get $a local.get $b f64.add))f64.sub, f64.mul, f64.div, f64.sqrt, f64.floor, f64.ceil, f64.min, and f64.max are all available. The same set exists for f32.
Comparison instructions
Section titled “Comparison instructions”Comparisons pop two values and push an i32 result: 1 for true, 0 for false. There is no boolean type — WebAssembly uses i32 as a boolean whenever it needs one.
(module ;; returns 1 if $a equals $b, else 0 (func (export "eq") (param $a i32) (param $b i32) (result i32) local.get $a local.get $b i32.eq)
;; signed less-than: returns 1 if $a < $b (signed), else 0 (func (export "ltSigned") (param $a i32) (param $b i32) (result i32) local.get $a local.get $b i32.lt_s))Comparison variants follow the same signed/unsigned pattern: i32.lt_s vs i32.lt_u, i32.gt_s vs i32.gt_u, i32.le_s, i32.ge_u, and so on.
Run it
Section titled “Run it”The example below compiles a module with subtraction, signed division, and a signed less-than comparison.