movq指令中40(%rdi)的40含义解析及GCC相关疑问
Understanding the
40 in movq 40(%rdi), %rax Let's break this down clearly, since you've already noticed some interesting patterns in GCC's generated code!
What does the 40 mean?
In x86-64 assembly, the syntax disp(base) refers to a base + displacement memory addressing mode. Here's exactly what's happening:
%rdiholds a memory address (the "base" address)- The
40is a fixed offset (displacement) that gets added to the base address in%rdi movq 40(%rdi), %raxreads an 8-byte (quadword, henceqinmovq) value from the memory address%rdi + 40, then stores that value into the%raxregister.
The parentheses () are indeed how you indicate "dereference this address"—just like the * operator in C for pointers.
Why does GCC always use multiples of 8?
Great observation! This ties directly to data alignment in C (and most high-level languages targeting x86-64):
- On x86-64 systems, the default alignment rule for 64-bit types (like pointers,
long long,double, or struct members that are 64-bit) is 8 bytes. This means these types are always stored at memory addresses that are multiples of 8. - When GCC generates code to access struct members, array elements, or other 64-bit values, it calculates their offset from the base pointer (
%rdimight be pointing to a struct instance, for example) as a multiple of 8 to maintain this alignment. - Aligned memory accesses are faster on x86-64 (the CPU can fetch the data in a single cycle), while unaligned accesses may require multiple cycles or even cause errors on some stricter architectures (though x86-64 allows them).
Why do non-multiples of 8 compile but give weird results?
x86-64 is lenient about unaligned memory access—your assembler won't throw an error because the architecture supports it. But here's why the results look like garbage:
movqalways reads 8 full bytes from the target address. When you use a displacement that's not a multiple of 8 (like 1, 2, or 7), you're starting the 8-byte read at an unaligned address.- For example, if you write
movq $1, (%rdi), you're storing the 8-byte value0x0000000000000001at%rdi. When you read1(%rdi), you're fetching 8 bytes starting at%rdi + 1: this includes the last 7 bytes of the0x0000000000000001(which are all 0) plus the first byte of whatever random data is stored at%rdi + 8. The combination of these bytes gives you that huge, nonsensical number in%rax. - Unaligned reads like this rarely make sense in real code—they're either accidental or used in very specific low-level scenarios (like parsing packed binary data).
内容的提问来源于stack exchange,提问作者sviamwvnb
相关产品推荐
相关产品推荐

