Sikau

WebAssembly · Day 2 · about 35 min

Numbers in the binary: LEB128

Variable-length integers: small numbers take one byte, big ones more.

Seven bits at a time

Wasm stores sizes, indexes and constants as LEB128: each byte carries 7 bits of the number, and its top bit says "more bytes follow". Small numbers (most of them) take one byte. Signed LEB128 is the same idea with the sign extended from bit 6 of the last byte.

Encode and decode

function encodeULEB128(n) {
  const out = [];
  do {
    let byte = n & 0x7f; // low 7 bits
    n >>>= 7;
    if (n !== 0) byte |= 0x80; // more bytes follow
    out.push(byte);
  } while (n !== 0);
  return out;
}

function encodeSLEB128(n) {
  const out = [];
  while (true) {
    const byte = n & 0x7f;
    n >>= 7; // arithmetic shift keeps the sign
    const done = (n === 0 && (byte & 0x40) === 0) || (n === -1 && (byte & 0x40) !== 0);
    if (done) {
      out.push(byte);
      return out;
    }
    out.push(byte | 0x80);
  }
}

function decodeULEB128(bytes, at = 0) {
  let value = 0;
  let shift = 0;
  let byte;
  do {
    byte = bytes[at++];
    value |= (byte & 0x7f) << shift;
    shift += 7;
  } while (byte & 0x80);
  return { value: value >>> 0, next: at };
}

The rest of this lesson

  • Encoding 300 by handexplain
  • Decodingexplain
  • Encode 300predict
  • Value to bytesmatch
  • LEB128 both wayswrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 8 lessons of WebAssembly