Data Movement & Arithmetic Instructions

Assembly Fundamentals

Chapter 5 · Data Movement & Arithmetic Instructions

ADD, AND, LD, LDR, and their relatives have already appeared in nearly every example since assembly1-1, always used a little informally. This chapter formalizes all of them properly — and, for the first time, opens up exactly how each one is encoded as actual bits, closing the loop assembly1-1 left open when it showed ADD R1, R0, R2 next to its raw binary form without explaining how one became the other.

LC-3's Instruction Set at a Glance

This chapter covers two families: the arithmetic/logic instructions, and the data-movement instructions whose addressing modes assembly1-3 already explained.

FamilyInstructionsWhat they do
Arithmetic / logicADD, AND, NOTOperate on register values, write a result back to a register
Load (memory → register)LD, LDR, LDI, LEABring a value (or an address) from memory into a register
Store (register → memory)ST, STR, STIWrite a register's value out to memory

Every load/store instruction pairs directly with one of assembly1-3's four addressing modes: LD/ST use PC-relative, LDI/STI use indirect, LDR/STR use base+offset, and LEA uses PC-relative too — but with a twist explained below.

ADD and AND — Two Operand Modes, One Mode Bit

ADD and AND are unusual among LC-3 instructions in that each one has two distinct forms, selected by a single bit in the instruction:

  • Register mode — both operands come from the register file: ADD R1, R0, R2 computes R0 + R2.
  • Immediate mode — one operand comes from a register, the other is a small constant embedded directly in the instruction (per assembly1-3's Immediate addressing mode): ADD R1, R0, #5 computes R0 + 5.
ADD R1, R0, R2   ; register mode — both operands are registers
ADD R1, R0, #5   ; immediate mode — second operand is a literal constant

NOT, by contrast, only has one form — it's a unary operation (one input, logically inverting every bit), so there's no second operand to choose a mode for at all: NOT R1, R0.

Opcode Format Anatomy

Every LC-3 instruction is 16 bits, and every one of them starts the same way: the top 4 bits (bits 15–12) are the opcode, identifying which of LC-3's operations this instruction is. 4 bits selects one of 16 possible opcodes (24 = 16) — the same bit-budget logic assembly1-3 and assembly1-4 already applied to addresses and registers, now applied to the operation itself.

ADD, Register Mode

0001opcode
DR3 bits
SR13 bits
0mode=0
00unused
SR23 bits

Bit 5 is the mode bit — 0 means register mode, and bits [2:0] name a second source register (SR2). DR is the destination register that receives the result.

ADD, Immediate Mode

0001opcode
DR3 bits
SR13 bits
1mode=1
imm55 bits, sign-extended

When bit 5 is 1, the remaining 5 bits are read as a signed immediate value instead of a second register — exactly this 5-bit width is why assembly1-3's immediate mode can only represent numbers from -16 to 15. AND is encoded identically, just with a different opcode (0101) in place of ADD's 0001.

NOT — A Fixed Pattern Instead of a Second Operand

1001opcode
DR3 bits
SR3 bits
111111always all 1s

Because NOT only ever needs one source register, it has no mode bit at all — the final 6 bits are simply always fixed to 111111 by the LC-3 specification, occupying the space a second operand would otherwise use.

LD — PC-Relative Load

0010opcode
DR3 bits
PCoffset99 bits, sign-extended

This is the exact bit layout behind the PC + SEXT(offset9) formula assembly1-3 introduced — the 9-bit field here is that offset. ST, LDI, and STI all follow this same DR/SR-plus-PCoffset9 shape (with different opcodes); LDR/STR instead use a 3-bit BaseR field plus a shorter 6-bit offset, matching assembly1-3's base+offset formula.

LEA never touches memory at all
LEA ("Load Effective Address") uses the exact same PC-relative bit layout as LD — but instead of reading the value stored at the computed address, it loads the address itself into the destination register. Combined with LDR's base+offset addressing from assembly1-3, this is exactly how you'd get an array's starting address into a register before indexing into it.
A 5-bit immediate is smaller than it looks
ADD R1, R1, #100 looks like ordinary arithmetic, but LC-3's immediate field is only 5 bits — signed, it can hold exactly -16 through 15. Anything larger simply can't be expressed as an immediate operand at all; the assembler will reject it, and the correct fix is to store the larger constant in memory with .FILL and LD it into a register instead.

Hands-On Exercises

Exercise 1

Given the 16-bit pattern 0001 010 011 1 00111, use this chapter's ADD bitfield diagrams to determine: which opcode this is, which mode (register or immediate), the destination register, the source register, and the operand's decimal value.

📄 View solution
Exercise 2

Explain, using this chapter's own bitfield diagrams, why ADD and AND need a mode bit but NOT doesn't — and what NOT's instruction has in the bit positions a mode bit and second operand would otherwise occupy.

📄 View solution
Exercise 3

Write LC-3 assembly that loads a value from memory location COUNT, adds 200 to it, and stores the result back to COUNT. Explain, using this chapter's warn-box, why a single ADD instruction with an immediate operand of 200 cannot be used here.

📄 View solution

Chapter 5 Quick Reference

  • ADD / AND — two forms each, register mode (bit 5 = 0) or immediate mode (bit 5 = 1, 5-bit signed operand, -16 to 15)
  • NOT — unary, no mode bit; its final 6 bits are always fixed to 111111
  • Every instruction's top 4 bits (15–12) are the opcode — 4 bits selects 1 of 16 possible operations
  • LD/ST/LDI/STI — DR/SR + a 9-bit PC-relative offset, the literal encoding behind assembly1-3's PC-relative formula
  • LDR/STR — DR/SR + a 3-bit base register + a 6-bit offset (base+offset addressing)
  • LEA — same layout as LD, but loads the computed address itself rather than the value stored there
  • A 5-bit immediate can only hold -16 to 15 — larger constants must live in memory and be loaded with LD