Search code examples
assemblyx86gnu-assemblerattaddressing-mode

x86 Assembly (Advanced Indexing Mode): How do I access memory at a variable amount ahead of a start address?


I am trying to read a section of memory, byte by byte, starting from the memory address stored in the EAX register. I push the current byte to the EBX register. However, when I execute the following line of code (advanced indexing mode):

movb byteCount(%eax), %ebx

I get the following error:

Program received signal SIGSEGV, Segmentation fault.

It seems that Assembly doesn't supporting using a label in advanced indexing. How would I go about emulating this same action without using a label or register before (%eax)? Below is the data section:

.data
    str:
        .string "abcdefg"
        
    byteCount:
        .int 1

Solution

  • In that context, byteCount is the label address, not the dword that happens to be in memory there. You need to load all runtime-variable things into registers to use them in addressing modes; x86 doesn't do memory-indirect addressing.

       mov    byteCount, %edx           # dword load
       movzbl (%eax, %edx), %ebx        # zero-extending byte load
    

    Or of course you could use add byteCount, %eax and deref (%eax). Or better, you could keep byteCount in a register in the first place, where you need it anyway. That's what registers are for. In x86 assembly, when should I use global variables instead of local variables? (usually you shouldn't).


    movb into EBX is an error (operand-size mismatch), so certainly that's not what you actually ran. But that would access a byte at bytecount[ (uintptr_t)eax ]. If you'd used just mov, it would be a dword load.

    But regardless, the sum of two addresses is rarely a valid address, so it segfaults. Your debugger should have told you the faulting address so you could see it was far from str.


    Related: