Sikau

Assembly language · Day 11 · about 40 min

Machine code

How add and addi become 32-bit numbers — encode and decode them in JavaScript.

Instructions are numbers

Text like add a0, a1, a2 is for humans. The assembler turns it into machine code: one 32-bit number per instruction, with fields for the opcode, the registers and constants. The CPU's decoder (remember fetch–decode–execute?) reads those fields.

  • R-type (add): funct7 | rs2 | rs1 | funct3 | rd | opcode — bits 31–25, 24–20, 19–15, 14–12, 11–7, 6–0.
  • I-type (addi): imm[11:0] | rs1 | funct3 | rd | opcode.
  • add has opcode 0x33, addi 0x13; both have funct3 = 0 (and add has funct7 = 0).
  • Registers are numbered: a0 is x10, a1 is x11, t0 is x5, zero is x0.

Shifting fields into place

function encodeAdd(rd, rs1, rs2) {
  return ((0 << 25) | (rs2 << 20) | (rs1 << 15) | (0 << 12) | (rd << 7) | 0x33) >>> 0;
}

function encodeAddi(rd, rs1, imm) {
  return (((imm & 0xfff) << 20) | (rs1 << 15) | (0 << 12) | (rd << 7) | 0x13) >>> 0;
}

function decode(word) {
  const opcode = word & 0x7f;
  const rd = (word >>> 7) & 31;
  const rs1 = (word >>> 15) & 31;
  if (opcode === 0x33 && ((word >>> 12) & 7) === 0 && word >>> 25 === 0) {
    return `add x${rd}, x${rs1}, x${(word >>> 20) & 31}`;
  }
  if (opcode === 0x13 && ((word >>> 12) & 7) === 0) {
    return `addi x${rd}, x${rs1}, ${word >> 20}`;
  }
  return "unknown";
}

The rest of this lesson

  • Decoding with shifts and masksexplain
  • Why big constants need two instructionsexplain
  • Decode itpredict
  • Field positions in an R-typematch
  • Assembler and disassemblerwrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 12 lessons of Assembly language