Just as we used opcodes to give names to bit strings representing instructions, we should give names to locations in the program. These location names are called labels.

A Label = a name that represents a memory address.

Typically, the memory address contains some designated instruction of the program. Labels are associated with two operations:

  1. defining (Define) a label in an assembly language program associates the name with the memory address at which the assembly language instruction after the label will be placed.
    1. Since labels are not present in machine language code, a Define in the assembly language program does not generate any words in the machine language code.
  2. using (Use) a label inserts the memory address corresponding to the label in the machine language code
    1. When generating machine language code, the assembler should output a word containing the address associated with the label in the Use.
	SLT(Reg(2) , Reg(1) , Reg(0)),
	BEQ(Reg(2) , Reg(0) ,1),
	SUB(Reg(1) , Reg(0) , Reg(1)),
// The equivalent using labels
val label = new Label("label")
	SLT(Reg(2), Reg(1), Reg(0)),
	beq(Reg(2), Reg(0), label),
	SUB(Reg(1), Reg(0), Reg(1)),

How an Assembler converts labels into memory addresses/offsets

Two passes over the code are necessary because the use of a label may occur before or after its definition:

  1. In the 1st pass, the assembler builds a Symbol Table, by mapping each label definition (everywhere Define(label) is called) to a memory address
  2. In the 2nd pass, the assembler uses the Symbol Table to translate each use of a label into the corresponding memory address or offset.