Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

x86-64 assembly: why offset 25 bytes?

Tags:

c++

assembly

I started learning x86 assembly today by analyzing the assembly code corresponding to this c++ example (I know there exists something like atoi but I wanted to keep the example minimal):

#include <vector>

std::vector<int> range(int N) {
    std::vector<int> v(N);
    for (unsigned int i = 0; i < N; ++i)
        v[i] = i;
    return v;
}

int main() {
    return range(100).back();
}

If compiled with g++ -O0 -S -fno-stack-protector return_by_value.cpp, this results in this excerpt:

... <snip>
_Z5rangei:
.LFB509:
    .cfi_startproc
    .cfi_personality 0x3,__gxx_personality_v0
    .cfi_lsda 0x3,.LLSDA509
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    pushq   %rbx
    subq    $40, %rsp
    .cfi_offset 3, -24
    movq    %rdi, -40(%rbp)
    movl    %esi, -44(%rbp)
    leaq    -25(%rbp), %rax
    movq    %rax, %rdi
    call    _ZNSaIiEC1Ev
    movl    $0, -24(%rbp)
    movl    -44(%rbp), %eax
    movslq  %eax, %rsi
    leaq    -25(%rbp), %rcx
    leaq    -24(%rbp), %rdx
    ... <snip>

I was surprised to see an odd (i.e. not multiple of 8) offset: leaq -25(%rbp), %rax, especially since it is a q instruction and further we have also -24(%rbp). For what reason is the compiler reading across 8 byte boundaries?

like image 365
Nibor Avatar asked Dec 23 '22 09:12

Nibor


1 Answers

Looking at this fragment:

leaq    -25(%rbp), %rax
movq    %rax, %rdi
call    _ZNSaIiEC1Ev

_ZNSaIiEC1Ev is demangled to std::allocator<int>::allocator(), so -25(%rbp) is the address of an allocator<int> object which is passed to the constructor. If we print the sizeof of this object in GCC we will get 1. Since the size of the object is 1, there is no need to align it to 8 bytes and it can be placed in any memory address.

The -24(%rbp) which you see later is the address of a different object, and the compiler is not reading across an 8-byte boundary.

Note that the lea instruction does not actually access memory - it only calculates an address. Therefore, the fact that it has a q suffix does not mean that it accesses 8 bytes.

like image 199
interjay Avatar answered Jan 02 '23 19:01

interjay