Я пытаюсь понять, как векторы работают на уровне сборки и когда я компилирую с g++ -masm=intel a.cpp && ./a.out
#include <vector>
#include <stdio.h>
#include <random>
using namespace std;
class Foo {
public:
int bar(vector<int>& v, int i) {
__asm__ __volatile__ (R"(
lea rax, [rsi + 32]
mov eax, [rax + rdx * 4]
;)");
}
};
int main() {
srand (time (NULL));
vector<int> v = {7, rand(),17,279,29,85};
for (int i = 0; i < v.size(); i++)
printf("%0d\n", Foo().bar(v, i));
return 0;
}
Приведенный выше код будет работать нормально, возвращая мои 6 чисел со случайным числом с индексом 1.
Мне очень приятно, так как я могу видеть содержимое моего массива, который правильно хранится в rsi + 32 (также хранится в rbp + 64), а rdx - это индекс, я умножаю на 4 с 4 байт в одно целое число.
Однако, если я скомпилирую с g++ a.cpp -O2 -masm=intel a.cpp && ./a.out
, программа будет зависать (также было 0 раз возвращено 6 раз)
Я знаю, что программа оптимизирована и вместо того, чтобы иметь «Нормальная» программа, с функцией вызывающего и вызываемого, я получаю следующую сборку с godbolt :
main:
sub rsp, 40
xor edi, edi
call time
mov rdi, rax
call srand
mov DWORD PTR [rsp], 7
call rand
mov edi, 24
mov DWORD PTR [rsp+4], eax
movabs rax, 1198295875601
mov QWORD PTR [rsp+8], rax
movabs rax, 365072220189
mov QWORD PTR [rsp+16], rax
call operator new(unsigned long)
movdqa xmm0, XMMWORD PTR [rsp]
mov rdx, QWORD PTR [rsp+16]
movups XMMWORD PTR [rax], xmm0
mov QWORD PTR [rax+16], rdx
lea rax, [rsi + 32]
mov eax, [rax + rdx * 4]
И следующую с hexdump -S в as:
.file "a.cpp"
.intel_syntax noprefix
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "%0d\n"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB2455:
.cfi_startproc
.cfi_personality 0x9b,DW.ref.__gxx_personality_v0
.cfi_lsda 0x1b,.LLSDA2455
push r12
.cfi_def_cfa_offset 16
.cfi_offset 12, -16
push rbp
.cfi_def_cfa_offset 24
.cfi_offset 6, -24
xor edi, edi
push rbx
.cfi_def_cfa_offset 32
.cfi_offset 3, -32
lea rbp, .LC0[rip]
mov ebx, 6
sub rsp, 32
.cfi_def_cfa_offset 64
mov rax, QWORD PTR fs:40
mov QWORD PTR 24[rsp], rax
xor eax, eax
call time@PLT
mov edi, eax
call srand@PLT
mov DWORD PTR [rsp], 7
call rand@PLT
mov DWORD PTR 4[rsp], eax
movabs rax, 1198295875601
mov edi, 24
mov QWORD PTR 8[rsp], rax
movabs rax, 365072220189
mov QWORD PTR 16[rsp], rax
.LEHB0:
call _Znwm@PLT
.LEHE0:
movdqa xmm0, XMMWORD PTR [rsp]
mov r12, rax
movups XMMWORD PTR [rax], xmm0
mov rax, QWORD PTR 16[rsp]
mov QWORD PTR 16[r12], rax
.p2align 4,,10
.p2align 3
.L2:
#APP
# 13 "a.cpp" 1
lea rax, [rsi + 32]
mov eax, [rax + rdx * 4]
;
# 0 "" 2
#NO_APP
xor edx, edx
mov rsi, rbp
mov edi, 1
xor eax, eax
.LEHB1:
call __printf_chk@PLT
.LEHE1:
sub rbx, 1
jne .L2
mov rdi, r12
call _ZdlPv@PLT
xor eax, eax
mov rcx, QWORD PTR 24[rsp]
xor rcx, QWORD PTR fs:40
jne .L10
add rsp, 32
.cfi_remember_state
.cfi_def_cfa_offset 32
pop rbx
.cfi_def_cfa_offset 24
pop rbp
.cfi_def_cfa_offset 16
pop r12
.cfi_def_cfa_offset 8
ret
.L10:
.cfi_restore_state
call __stack_chk_fail@PLT
.L5:
mov rbx, rax
mov rdi, r12
call _ZdlPv@PLT
mov rdi, rbx
Я (пока) не могу свободно читать ассемблер, поэтому у меня возникают проблемы с поиском того, как заставить этот встроенный код ассемблера работать с флагом оптимизации. Любая помощь будет принята с благодарностью!
PS: Я уже прочитал эту ссылку , но это не помогает.