A label names the current byte offset in a section. It lets instructions and data refer to locations without hard-coding the final address:
.section my_data first: .word 11 second: .word 22
first has section-relative value zero; second has value four because one word occupies four bytes. Neither declaration itself emits bytes. Once the linker places the section, a label's address is:
$$ A_{\mathrm{label}}=B_{\mathrm{section}}+V_{\mathrm{label}} $$
Here $B_{\mathrm{section}}$ is the section's base address and $V_{\mathrm{label}}$ is the recorded offset. Moving the section changes both addresses while preserving their four-byte separation.
A use such as ld $second, %r1 requests the label's address; ld second, %r1 requests the value stored there. The assembler can record an unresolved symbol use before encountering its definition, leaving the required relocation for linking.
Labels are local unless exported with `.global`. Their names provide identity, while their section and value determine location; the eventual address need not appear literally in the source.
Source: asembler.c.