Labels and data
Naming addresses so you don't count bytes
A label is a name for a memory address in assembly language; the assembler builds a symbol table mapping each label to the address its line lands at, so you can write LOAD x instead of a hardcoded number and reserve data bytes with a directive like x: .byte 5.
Builds onAssembly language
Writing
LOAD 14 works, but it is brittle. If you add one instruction near the top, every later address shifts by one and every hardcoded number is now wrong. Real assembly avoids this with labels: you name a location once, and the assembler works out the actual address for you. You stop counting bytes.A label names a location
A label is a name written before an instruction or a piece of data, like
x:. It marks *this address* with a name. Elsewhere you use the name as an operand, LOAD x, and the assembler substitutes the real address. To set aside a byte of data, a directive like .byte reserves memory with an initial value: x: .byte 5 means "a byte named x, starting at 5." Directives are instructions to the assembler, not the CPU; they shape memory rather than becoming opcodes. LOAD x ; ACC = x
ADD y ; ACC = x + y
STORE z ; z = ACC
HALT
x: .byte 6 ; a named data byte
y: .byte 9
z: .byte 0 ; the result lands hereHow the assembler resolves labels
The assembler makes two passes. On the first pass it walks the program assigning each line an address in order (the four instructions take addresses 0 to 3, then the data bytes take 4, 5, 6), and it records every label in a symbol table:
x = 4, y = 5, z = 6. On the second pass it emits the bytes, replacing each label operand with its address from the table. LOAD x becomes LOAD 4, byte 0x14; ADD y becomes ADD 5, byte 0x25.symbol table addr byte source
x = 4 0 0x14 LOAD x (LOAD 4)
y = 5 1 0x25 ADD y (ADD 5)
z = 6 2 0x36 STORE z (STORE 6)
3 0xF0 HALT
4 0x06 x: .byte 6
5 0x09 y: .byte 9
6 0x00 z: .byte 0This is a real, if tiny, program layout: code first, then data, both in the same memory. That single shared memory for instructions and data is the *von Neumann* idea, the same bytes are code when the program counter fetches them and data when a
LOAD reads them. The assembler's job is just to lay everything out and turn names into addresses.The operand is only 4 bits, so every label must resolve to an address in
0 to 15, and the whole program (code plus data) has to fit in the machine's 16 bytes. Labels make addresses readable, but they cannot create memory that is not there. A bigger program needs a CPU with a wider address, exactly the pressure that grows real instruction sets.Try it
In the assembled program above, why is the byte for
LOAD x equal to 0x14 and not, say, 0x1x? What did the assembler have to know first?Answer
The assembler first had to place
x in memory and record its address in the symbol table: x landed at address 4. Only then could it resolve LOAD x to LOAD 4 and pack opcode 0x1 (LOAD) with operand 0x4 into the byte 0x14. The label is a name; the byte needs the actual address, which is why the assembler does a placing pass before it emits any bytes.Frequently asked
What is a label in assembly language?
A label is a name for a memory address, written before an instruction or data (like x:). You then use the name as an operand (LOAD x) and the assembler substitutes the real address. Labels let you avoid hardcoding numbers that break whenever the program's layout shifts.
What is a symbol table in an assembler?
A symbol table is the map from each label to the address it lands at, built by the assembler as it walks the program. On a first pass it assigns addresses and fills the table (x=4, y=5, z=6); on a second pass it emits bytes, replacing each label with its address.
Why does an assembler make two passes?
A label can be used before it is defined, so the assembler cannot know an operand's address on the first read. Pass one assigns every line an address and records all labels; pass two emits the bytes with each label resolved to its now-known address.
How do you reserve data in assembly?
With a directive such as .byte: writing x: .byte 5 tells the assembler to set aside one byte named x with the initial value 5. Directives shape memory for the assembler rather than becoming CPU opcodes, unlike LOAD or ADD which do.
Every lesson here builds toward one thing: a working CPU, from the transistor up.
Open the free lab →