Code symbols are defined in (LABEL) statements. Their value is set to the ROM address of the next asm command.  For example, this program adds the numbers from 1 to 100.
// Sum1.asm -- Set RAM[2] = 1 + 2 + ... + 100
    @100
    D=A
    @1
    M=D     // RAM[1] = 100
    @2
    M=0     // RAM[2] = 0
(LOOP)
    @1
    D=M
    @2
    M=M+D   // RAM[2] = RAM[2] + RAM[1]
    @1
    MD=M-1  // D = RAM[1] = RAM[1]-1
    @LOOP
    D;JGT   // repeat while D > 0
(HALT)
    @HALT
    0;JMP   // loop forever
In this program, LOOP will get value 6 and HALT will get value 14.
When an @ command uses a symbol that is not code symbol, that symbol is assumed to be a variable (RAM symbol). Here's the Sum program using variables instead of absolute RAM addresses.
// Sum2.asm -- Set variable 'sum' = 1 + 2 + ... + 100
    @100
    D=A
    @n
    M=D     // n = 100
    @sum
    M=0     // sum = 0
(LOOP)
    @n
    D=M
    @sum
    M=M+D   // sum = sum + n
    @n
    MD=M-1  // D = n = n-1
    @LOOP
    D;JGT   // repeat while D > 0
(HALT)
    @HALT
    0;JMP   // loop forever
The first time the Assembler or CPUEmulator encounters a symbol that is not a code symbol, it automatically assigns a RAM address to that symbol, starting with address 16.
In this case, the first non-code symbol is 'n' so it gets address 16 and 'sum' will get address 17.
(Note that it's my convention, not a requirement, that code labels are all UPPERCASE and data symbols are all lowercase or mixedCase.)
--Mark