Есть структура: Код (Text): typedef struct { CHAR szName[20]; DWORD dwIndex; // .... etc } REGULAR_CONTAINER_DATA; Общий размер структуры 80 байт. Понадобилось оформить функцию, которой аргументом нужно передать данную структуру. Передать именно через стек, а не указателем. Да, можно выделить память и передать указатель на нее функции, либо много других разных вариантов. Но меня интересует именно этот. Реально ли научить компилятор передавать всю структуру целиком в стек (т.е. не push [pContainerData], а что-то вроде push [part_1], push [part_2], push ... и так всю структуру)?
Обычно компилятор копирует структуру и передает в функцию указатель на скопированную структуру(чтобы не затереть оригинал). При таком подходе результат будет точно таким же, как если бы структура передавалась в стек по частям командами push. Вы объясните зачем это вообще нужно, может тогда легче будет вам помочь.
В stdcall, cdecl и ms-fastcall передаётся не указатель на копию, а именно сама структура (цепочка push, если структура небольшая, в противном случае какой-нибудь movsd). То, о чём вы говорите – оптимизация, когда конвенцию вызовов можно безболезненно нарушить (например, функция статическая и на неё нигде не берётся указатель).
сомнительно. Может быть вы путаете цепочку пушей при создании КАДРА? потому что локальные переменные одной процедуры могут передаваться в кадрах вложенным процедурам. Особенно с учетом, что ENTER/LEAVE не самые оптимальные по скорости. Иначе передавать структуру через стек как-то кривовато, хоть какое соглашение используй. А как байтовые члены структур передаются? или 2-байтовые? А если размер структуры не кратен 4?
Я давно уже не ковырялся в соглашениях, но вроде ничего не путаю. Как минимум можно посмотреть, что будет в retn у кода ниже, а будет там не размер указателя явно: Код (Text): struct t { int data[256]; }; void __stdcall foo(struct t arg) { return; } И я не понимаю, причём тут члены – вот если размер структуры не кратнен 4 будет, её, видимо, выравняют на 4 (а как иначе-то?) перед передачей. Это я всё про 32 бита, если что. Вот при возврате структур – там да, указатели. Если размер структуры не равен 1/2/4/8 байтам (иначе она преспокойно возвращается в AL/AX/EAX/EDX:EAX), вызывающая функция создаёт буфер, передаёт первым аргументом указатель на него, а вызываемая функция копирует результат туда и дополнительно возвращает тот же самый указатель в EAX.
Sholar Код и дизасм в студию. У меня вызов foo в следующей функции (пришлось подкорректировать во избежание оптимизаций): Код (Text): struct t { int data[256]; }; void __stdcall foo(struct t arg, int num) { printf("%u", arg.data[num]); if (num < 50) { arg.data[num] = num; foo(arg, num+1); } return; } выглядит так: Код (Text): Address Hex dump Command 00FC104C |. 46 INC ESI 00FC104D |. 56 PUSH ESI 00FC104E |. 81EC 00040000 SUB ESP,400 00FC1054 |. 8BFC MOV EDI,ESP 00FC1056 |. B9 00010000 MOV ECX,100 00FC105B |. 8DB5 FCFBFFFF LEA ESI,[EBP-404] 00FC1061 |. F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] 00FC1063 |. E8 98FFFFFF CALL foo Т.е. никаких указателей. Вся структура прямо в стек уходит. P.S. Ага. Уже сами разобрались. Ну и ладно.