jcxz 240 9 февраля, 2015 Опубликовано 9 февраля, 2015 · Жалоба Компилатор формирует при вызове функции место в стеке и передает адрес на эту область в функцию. В самой функции структура - локальная переменная (в стеке). Для возвращения структуры компилятор копирует поля локальной структуры по тому адресу, который предоставила функция. По сути у функции есть еще один "невидимый" входной параметр - адрес для возврата. Не смотрел в листинг, но сомневаюсь что компилятор что-то передаёт неявно в функцию (кроме указателя this член-функциям), так как соглашения вызова расписаны и там нет предусмотрено это. Да и незачем. Если функция возвращает структуру, то она "сама об этом знает". И она знает, что вызывающая функция позаботилась о месте в стеке, и просто вычисляет адрес, исходя из SP в точке входа в функцию. Думаю так. Вообще - это дефолтный способ передачи и возврата параметров в функцию - через стек. И только оптимизатор заменяет стек на входе и выходе функции на регистры (если может и это не запрещено опциями). Так что компилятор в точке вызова функции по дефолту должен сперва сформировать стековый фрейм для возвращаемого значения (вне зависимости от его типа), а потом поместить в него входные аргументы вызова. И ещё замечание: насколько я знаю, некоторые компиляторы (согласно соглашениям вызова) могут возвращать не в одном регистре, а в паре. Т.е. в IAR for ARM - если возвращаемое значение - long long, то используется регистровая пара R0:R1, а не стек. То же самое и для структур - если размер структуры влезает в одну регистровую пару, то она будет возвращена через регистры (один R0 или пару R0:R1), а не через стек. Вроде так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 9 февраля, 2015 Опубликовано 9 февраля, 2015 · Жалоба Не смотрел в листинг, но сомневаюсь что компилятор что-то передаёт неявно в функцию Вот неверующих-то развелось :) Вообще-то, это в документации на ABI прописано. Вот пример: typedef struct { int a; int b; int c; } T; T my_func (int a) { T v; v.a = a; v.b = ~a; v.c = -a; return v; } static T s; void my_func1(int a) { s = my_func(a); } а вот фрагмент вызова ф-ции: ; 30 : ; 31 : s = my_func(a); mov eax, DWORD PTR _a$[ebp] push eax lea ecx, DWORD PTR $T792[ebp] push ecx call _my_func add esp, 8 mov edx, DWORD PTR [eax] mov DWORD PTR _s, edx mov ecx, DWORD PTR [eax+4] mov DWORD PTR _s+4, ecx mov edx, DWORD PTR [eax+8] mov DWORD PTR _s+8, edx push eax - педерача параметра "a" lea и push ecx - неявная передача указателя на область стека для возврата структуры затем вызов функции, и копирование результата в статическую переменную. А вот если бы структура состояла бы из двух int, а не трех - то все бы упростилось. Оба поля вернулись бы в edx:eax без стека и неявных указателей. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Grizzly 0 9 февраля, 2015 Опубликовано 9 февраля, 2015 · Жалоба Не смотрел в листинг, но сомневаюсь что компилятор что-то передаёт неявно в функцию (кроме указателя this член-функциям), так как соглашения вызова расписаны и там нет предусмотрено это. Да и незачем. В компиляторе VC 2005 в функцию передается на регистре адрес зарезервированный области. Возможно, в более поздних версиях и других компиляторах этого нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SM 0 9 февраля, 2015 Опубликовано 9 февраля, 2015 · Жалоба Возможно, в более поздних версиях и других компиляторах этого нет. Везде есть. Совместимость то по ABI у них полная. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Grizzly 0 9 февраля, 2015 Опубликовано 9 февраля, 2015 · Жалоба а вот фрагмент вызова ф-ции: Спасыб! ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slavka012 0 13 марта, 2015 Опубликовано 13 марта, 2015 · Жалоба А никто так и не делает. Возвращают данные, которые компилятор неявно копирует из локальной переменной в lvalue, указатель на который также неявно передается в ф-цию. То есть, возвращаются только данные. Компилятор ничего подобного не делает, и никаких "неявных адресов возврата" в функцию не передается. Функция находит свои параметры, локальные переменные и результат относительно указателя стека. В компиляторе VC 2005 в функцию передается на регистре адрес зарезервированный области. Возможно, в более поздних версиях и других компиляторах этого нет. Какой еще зарезервироавнной области? Что вы такое говорите? "С" calling convention никто не отменял и компилятор того что вы говорите просто не может делать. Я думаю вы неправильно поняли листинг. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
xvr 12 16 марта, 2015 Опубликовано 16 марта, 2015 · Жалоба Какой еще зарезервироавнной области? Что вы такое говорите? "С" calling convention никто не отменял и компилятор того что вы говорите просто не может делать. Я думаю вы неправильно поняли листинг.Ох уж эти сказочники :rolleyes: 'Не может, не может', еще и "С" calling convention сюда приплели Вот, выдержка из вашего любимого calling conversion (прямо с сайта MS) On x86 plaftorms, all arguments are widened to 32 bits when they are passed. Return values are also widened to 32 bits and returned in the EAX register, except for 8-byte structures, which are returned in the EDX:EAX register pair. Larger structures are returned in the EAX register as pointers to hidden return structures. Parameters are pushed onto the stack from right to left. Structures that are not PODs will not be returned in registers. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться