Skip to main content
Engineering LibreTexts

8.1: Addresses and Values

  • Page ID
    19904
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    On a 64-bit architecture, addresses require 64-bits.

    As noted in the previous chapter, the only way to access memory is with the brackets ([]'s). Omitting the brackets will not access memory and instead obtain the address of the item. For example:

        mov     rax, qword [var1]         ; value of var1 in rax 
        mov     rax, var1                 ; address of var1 in rax
    

    Since omitting the brackets is not an error, the assembler will not generate error messages or warnings.

    When accessing memory, in many cases the operand size is clear. For example, the instruction

        mov     eax, [rbx]
    

    moves a double-word from memory. However, for some instructions the size can be ambiguous. For example,

        inc [rbx]                         ; error
    

    is ambiguous since it is not clear if the memory being accessed is a byte, word, or double-word. In such a case, operand size must be specified with either the byte, word, or dword, qword size qualifier. For example,

        inc byte [rbx] 
        inc word [rbx] 
        inc dword [rbx]
    

    each instruction requires the size specification in order to be clear and legal.

    Register Mode Addressing

    Register mode addressing means that the operand is a CPU register (eax, ebx, etc.). For example:

        mov     eax, ebx
    

    Both eax and ebx are in register mode addressing.

    Immediate Mode Addressing

    Immediate mode addressing means that the operand is an immediate value. For example:

        mov     eax, 123
    

    The destination operand, eax , is register mode addressing. The 123 is immediate mode addressing. It should be clear that the destination operand in this example cannot be immediate mode.

    Memory Mode Addressing

    Memory mode addressing means that the operand is a location in memory (accessed via

    an address). This is referred to as indirection or dereferencing.
    The most basic form of memory mode addressing has been used extensively in the

    previous chapter. Specifically, the instruction:

        mov     rax, qword [qNum]
    

    Will access the memory location of the variable qNum and retrieve the value stored there. This requires that the CPU wait until the value is retrieved before completing the operation and thus might take slightly longer to complete than a similar operation using an immediate value.

    When accessing arrays, a more generalized method is required. Specifically, an address can be placed in a register and indirection performed using the register (instead of the variable name).

    For example, assuming the following declaration:

        lst     dd     101, 103, 105, 107

    The decimal value of 101 is 0x00000065 in hex. The memory picture would be as follows:

    Value

    Address

    Offset

    Index

    00

    0x6000ef

    lst + 15

    00

    0x6000ee

    lst + 14

    00

    0x6000ed

    lst + 13

    6b

    0x6000ec

    lst + 12

    lst[3]

    00

    0x6000eb

    lst + 11

    00

    0x6000ea

    lst + 10

    00

    0x6000e9

    lst + 9

    69

    0x6000e8

    lst + 8

    lst[2]

    00

    0x6000e7

    lst + 7

    00

    0x6000e6

    lst + 6

    00

    0x6000e5

    lst + 5

    67

    0x6000e4

    lst + 4

    lst[1]

    00

    0x6000e3

    lst + 3

    00

    0x6000e2

    lst + 2

    00

    0x6000e1

    lst + 1


    lst →

    65

    0x6000e0

    lst + 0

    lst[0]

    The first element of the array could be accessed as follows:

        mov    eax, dword [1st]

    Another way to access the first element is as follows:

        mov     rbx, list
        mov     eax, dword [rbx]
    

    In this example, the starting address, or base address, of the list is placed in rbx (first line) and then the value at that address is accessed and placed in the rax register (second line). This allows us to easily access other elements in the array.

    Recall that memory is “byte addressable”, which means that each address is one byte of information. A double-word variable is 32-bits or 4 bytes so each array element uses 4 bytes of memory. As such, the next element (103) is the starting address (lst) plus 4, and the next element (105) is the starting address (lst) 8.

    Increasing the offset by 4 for each successive element. A list of bytes would increase by 1, a list of words would increase by 2, a list of double-words would increase by 4, and a list of quadwords would increase by 8.

    The offset is the amount added to the base address. The index is the array element number as used in a high-level language.

    There are several ways to access the array elements. One is to use a base address and add a displacement. For example, given the initializations:

        mov     rbx, lst 
        mov     rsi, 8
    

    Each of the following instructions access the third element (105 in the above list).

        mov     eax, dword [lst+8] 
        mov     eax, dword [rbx+8] 
        mov     eax, dword [rbx+rsi]
    

    In each case, the starting address plus 8 was accessed and the value of 105 placed in the eax register. The displacement is added and the memory location accessed while none of the source operand registers (rbx, rsi) are altered. The specific method used is up to the programmer.

    In addition, the displacement may be computed in more complex ways.

    The general format of memory addressing is as follows:

         [ baseAddr + (indexReg * scaleValue ) + displacement ]
    

    Where baseAddr is a register or a variable name. The indexReg must be a register. The scaleValue is an immediate value of 1, 2, 4, 8 (1 is legal, but not useful). The displacement must be an immediate value. The total represents a 64-bit address.

    Elements may be used in any combination, but must be legal and result in a valid address.

    Some example of memory addressing for the source operand are as follows:

         mov     eax, dword [var1]
         mov     rax, qword [rbx+rsi]
         mov     ax, word [lst+4]
         mov     bx, word [lst+rdx+2]
         mov     rcx, qword [lst+(rsi*8)] 
         mov     al, byte [buff-1+rcx]
         mov     eax, dword [rbx+(rsi*4)+16] 
    

    For example, to access the 3rd element of the previously defined double-word array (which is index 2 since index's start at 0):

         mov     rsi, 2                             ; index=2 
         mov     eax, dword [lst+rsi*4]             ; get lst[2]

    Since addresses are always qword (on a 64-bit architecture), a 64-bit register is used for the memory mode addressing (even when accessing double-word values). This allows a register to be used more like an array index (from a high-level language).

    For example, the memory operand, [lst+rsi*4], is analogous to lst[rsi] from a high-level language. The rsi register is multiplied by the data size (4 in this example since each element is 4 bytes).


    This page titled 8.1: Addresses and Values is shared under a CC BY-NC-SA license and was authored, remixed, and/or curated by Ed Jorgensen.

    • Was this article helpful?