Search code examples
assemblyx86attaddressing-mode

Assembly, x86: How to push a label to the stack?


given the data:

.section data
data_set:
.long 2,5,33,54,2,76,4,37,43,223,98,70,255

how do I push the start address of the data (and not the value in that address) to the stack?

I tried this:

pushl data_set

which eventually (after trying to access the data in this address) resulted in a segfault.


Solution

  • In AT&T syntax, to use an address as an immediate operand to an instruction, use $label.

    You want pushl $data_set for the push imm32 instruction., like you would push $123.

    pushl data_set would push a dword of data loaded from the address data_set, i.e.
    push m32.


    Conceptually, AT&T syntax treats everything as a potential address. So label is an address, and so is 0x123. So add 0x123, %eax loads from the address 0x123, and add label, %eax loads from the address label. When you want a number as an immediate operand, you use add $0x123, %eax. Using a symbol address as an immediate operand works identically.

    Either way, the address is encoded into the instruction, it's just a question of whether it's as an immediate or as a displacement in an addressing mode. This is why you use
    add $(foo - bar), %eax to add the distance between two symbols, instead of
    add $foo-$bar, %eax (which would look for a symbol called $bar, i.e. the $ is part of the symbol name). The $ applies to the whole operand, not to symbol / label names. Related: more about assemble-time math in GAS

    In other contexts, e.g. as an operand to .long or .quad, there's no immediate vs. memory operand issue, so you just write dataptr: .long data_set to emit 4 bytes of data holding the address of data_set, like you'd get from C static int *dataptr = data_set;


    You could have checked on the syntax by looking at C compiler output for

    void ext(int*);
    static int data[] = {1,2,3};
    void foo() {
        ext(data);
    }
    

    to get the C compiler to emit code passing a symbol address to a function. I put this on the Godbolt compiler explorer, where it does indeed use pushl $data.