реклама на сайте
подробности

 
 
2 страниц V  < 1 2  
Reply to this topicStart new topic
> Возврат структуры из функции, косяк Кернигана-Ричи
jcxz
сообщение Feb 9 2015, 12:09
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Grizzzly @ Feb 9 2015, 13:26) *
Компилатор формирует при вызове функции место в стеке и передает адрес на эту область в функцию. В самой функции структура - локальная переменная (в стеке). Для возвращения структуры компилятор копирует поля локальной структуры по тому адресу, который предоставила функция. По сути у функции есть еще один "невидимый" входной параметр - адрес для возврата.

Не смотрел в листинг, но сомневаюсь что компилятор что-то передаёт неявно в функцию (кроме указателя this член-функциям), так как соглашения вызова расписаны и там нет предусмотрено это. Да и незачем.
Если функция возвращает структуру, то она "сама об этом знает". И она знает, что вызывающая функция позаботилась о месте в стеке, и просто вычисляет адрес, исходя из SP в точке входа в функцию. Думаю так.
Вообще - это дефолтный способ передачи и возврата параметров в функцию - через стек. И только оптимизатор заменяет стек на входе и выходе функции на регистры (если может и это не запрещено опциями).
Так что компилятор в точке вызова функции по дефолту должен сперва сформировать стековый фрейм для возвращаемого значения (вне зависимости от его типа), а потом поместить в него входные аргументы вызова.

И ещё замечание: насколько я знаю, некоторые компиляторы (согласно соглашениям вызова) могут возвращать не в одном регистре, а в паре. Т.е. в IAR for ARM - если возвращаемое значение - long long, то используется
регистровая пара R0:R1, а не стек. То же самое и для структур - если размер структуры влезает в одну регистровую пару, то она будет возвращена через регистры (один R0 или пару R0:R1), а не через стек.

Вроде так.
Go to the top of the page
 
+Quote Post
SM
сообщение Feb 9 2015, 12:41
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(jcxz @ Feb 9 2015, 15:09) *
Не смотрел в листинг, но сомневаюсь что компилятор что-то передаёт неявно в функцию

Вот неверующих-то развелось sm.gif Вообще-то, это в документации на 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 без стека и неявных указателей.
Go to the top of the page
 
+Quote Post
Grizzzly
сообщение Feb 9 2015, 12:42
Сообщение #18


Знающий
****

Группа: Свой
Сообщений: 565
Регистрация: 22-02-13
Пользователь №: 75 748



Цитата(jcxz @ Feb 9 2015, 15:09) *
Не смотрел в листинг, но сомневаюсь что компилятор что-то передаёт неявно в функцию (кроме указателя this член-функциям), так как соглашения вызова расписаны и там нет предусмотрено это. Да и незачем.

В компиляторе VC 2005 в функцию передается на регистре адрес зарезервированный области. Возможно, в более поздних версиях и других компиляторах этого нет.
Go to the top of the page
 
+Quote Post
SM
сообщение Feb 9 2015, 12:43
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 7 946
Регистрация: 25-02-05
Из: Moscow, Russia
Пользователь №: 2 881



Цитата(Grizzzly @ Feb 9 2015, 15:42) *
Возможно, в более поздних версиях и других компиляторах этого нет.

Везде есть. Совместимость то по ABI у них полная.
Go to the top of the page
 
+Quote Post
Grizzzly
сообщение Feb 9 2015, 12:45
Сообщение #20


Знающий
****

Группа: Свой
Сообщений: 565
Регистрация: 22-02-13
Пользователь №: 75 748



Цитата(SM @ Feb 9 2015, 15:41) *
а вот фрагмент вызова ф-ции:

Спасыб! wink.gif
Go to the top of the page
 
+Quote Post
ar__systems
сообщение Mar 13 2015, 15:17
Сообщение #21


self made
****

Группа: Свой
Сообщений: 855
Регистрация: 7-03-09
Из: Toronto, Canada
Пользователь №: 45 795



Цитата(SM @ Feb 9 2015, 03:29) *
А никто так и не делает. Возвращают данные, которые компилятор неявно копирует из локальной переменной в lvalue, указатель на который также неявно передается в ф-цию. То есть, возвращаются только данные.


Компилятор ничего подобного не делает, и никаких "неявных адресов возврата" в функцию не передается.

Функция находит свои параметры, локальные переменные и результат относительно указателя стека.


Цитата(Grizzzly @ Feb 9 2015, 07:42) *
В компиляторе VC 2005 в функцию передается на регистре адрес зарезервированный области. Возможно, в более поздних версиях и других компиляторах этого нет.

Какой еще зарезервироавнной области? Что вы такое говорите? "С" calling convention никто не отменял и компилятор того что вы говорите просто не может делать. Я думаю вы неправильно поняли листинг.
Go to the top of the page
 
+Quote Post
XVR
сообщение Mar 16 2015, 12:21
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(ar__systems @ Mar 13 2015, 18:17) *
Какой еще зарезервироавнной области? Что вы такое говорите? "С" calling convention никто не отменял и компилятор того что вы говорите просто не может делать. Я думаю вы неправильно поняли листинг.
Ох уж эти сказочники rolleyes.gif 'Не может, не может', еще и "С" calling convention сюда приплели biggrin.gif
Вот, выдержка из вашего любимого 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.

Go to the top of the page
 
+Quote Post

2 страниц V  < 1 2
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th July 2025 - 18:04
Рейтинг@Mail.ru


Страница сгенерированна за 0.0142 секунд с 7
ELECTRONIX ©2004-2016