2017-01-03 12 views
8

У меня есть следующий C++ код:Что касается C++ и Assembly, что такое ebp + 8?

#include <tuple> 
std::tuple<int, bool> foo() 
{ 
    return std::make_tuple(128, true); 
} 
int main() 
{ 
    auto result = foo(); 
} 

Ниже приводится разобранная версия функции foo():

push ebp 
mov  ebp, esp 
sub  esp, 24 
mov  BYTE PTR [ebp-13], 1 // second argument 
mov  DWORD PTR [ebp-12], 128 // first argument 
mov  eax, DWORD PTR [ebp+8] // what is this? why we need this here? 
sub  esp, 4 
lea  edx, [ebp-13] 
push edx     // second 
lea  edx, [ebp-12] 
push edx     // first 
push eax     // same as "ebp+8", what is this? 
call std::tuple<std::__decay_and_strip<int>::__type, std::__decay_and_strip<bool>::__type> std::make_tuple<int, bool>(int&&, bool&&) 
add  esp, 12 
mov  eax, DWORD PTR [ebp+8] 
leave 
ret  4 

Как я знаю ebp+X для аргументов функции доступа, но нет ничего подобного для foo, так почему же компилятор его использует? Кажется, что это первый параметр для std::make_tuple().

EDIT:

Я не использую оптимизацию, я просто хочу, чтобы узнать RE.

Часть основных в Ассамблее:

lea  eax, [ebp-16] // loaction of local variable 
sub  esp, 12 
push eax   // as hidden argument for foo 
call foo() 
add  esp, 12 
+0

Какой уровень оптимизации, версия компилятора, параметры компилятора и другие параметры? –

+0

@NickC без какой-либо оптимизации. gcc -m32 c.cpp –

+1

https://www.cs.uaf.edu/2005/fall/cs301/support/x86/index.html –

ответ

12

Вызывающая конвенция определяет, что нетривиальные объекты возвращаются через скрытый указатель передается в качестве аргумента. Это то, что вы видите. Технически ваш код реализован следующим образом:

std::tuple<int, bool>* foo(std::tuple<int, bool>* result) 
{ 
    *result = std::make_tuple(128, true); 
    return result; 
} 
int main() 
{ 
    std::tuple<int, bool> result; 
    foo(&result); 
} 
+0

У меня были такие мысли :)) thanks: d –

+0

Если вы посмотрели, как это было вызвано, это могло бы также помочь;) Кроме того, обратитесь к соответствующей документации соглашения о вызовах. – Jester

+0

push eax; call foo(); –