0 / 0 / 1
Регистрация: 09.10.2017
Сообщений: 27
1
Delphi 6-7

Команды push EBP и pop ECX при вызове процедуры

16.11.2023, 10:59. Показов 587. Ответов 8

Author24 — интернет-сервис помощи студентам
И здравствуйте!
Недавно стало интересно, какой ассемблерный код генерирует Delphi при компиляции программы, и вот какую странную вещь я обнаружил.
Иногда перед вызовом процедуры без параметров Delphi зачем-то ставит команду "push EBP", а после вызова - команду "pop ECX".
Кто-нибудь знает, зачем она так делает?
Миниатюры
Команды push EBP и pop ECX при вызове процедуры   Команды push EBP и pop ECX при вызове процедуры   Команды push EBP и pop ECX при вызове процедуры  

Команды push EBP и pop ECX при вызове процедуры  
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.11.2023, 10:59
Ответы с готовыми решениями:

Как работают команды pop() и push()
Здравствуйте, подскажите, как работают команды, пожалуйста гугл мне упрямо не хочет дать нужную...

Команды, работающие со стеком без push, pop
Необходимо написать последовательность команд, работающие со стеком без использования pop и push c...

Сделать так чтобы если вводится push выполнялась функция push, если pop то pop
Помогите пожалуйста с данным вопросом: например у меня есть список и несколько возможных с ним...

Какие обращения к памяти осуществляется при выполнении команды LFS EDI, [EBP+4] в защищенном режиме?
Какие обращения к памяти осуществляется при выполнении команды LFS EDI, в защищенном режиме МП...

Push, Pop
Вот такое задание: F=Ʃ от 1 до 5 f (Ai) A1=2 Ai+1=Ai+2 Ai=(3*A)+(C/D). Нужно записать эту...

8
4164 / 1816 / 216
Регистрация: 06.10.2010
Сообщений: 4,069
24.11.2023, 13:45 2
Регистр ebp используется для адресации локальных переменных (при соглашении stdcall ещё и параметров). По соглашению о вызове функция не должна его изменять, поэтому производится сохранение регистра в стек.

Типичный код процедуры
Assembler
1
2
3
4
5
6
7
8
push ebp
mov ebp,esp
 
//тут код процедуры
 
mov esp,ebp
pop ebp
ret
pop ecx - это просто выкидывание параметра из стека. Похоже процедура _Test_LocalVars вызывается по соглашению cdecl.
0
0 / 0 / 1
Регистрация: 09.10.2017
Сообщений: 27
24.11.2023, 18:35  [ТС] 3
1. В Delphi каждая процедура сама сохраняет регистр EBP - сразу после своего вызова - и сама его восстанавливает - непосредственно перед завершением своей работы.
2. В данном случае, перед вызовом процедуры _Test_LocalVars Delphi просто резервирует место в стеке. Зачем она это делает - большая загадка.
3. И вообще, непонятно, зачем функция _Test_LocalVars формирует стековый кадр (сохраняет в стеке регистр EBP), ведь у нее нет ни аргументов, ни локальных переменных. Для доступа к локальной переменной родительской функции (т.е. Test_LocalVars_06c) она вполне могла бы использовать формулу [EBP+N], где N - соответствующее смещение этой переменной.
Короче, налицо двойная глупость Delphi.
А соглашение о вызовах процедур по умолчанию - pascal. Я его не менял.
Миниатюры
Команды push EBP и pop ECX при вызове процедуры  
0
4164 / 1816 / 216
Регистрация: 06.10.2010
Сообщений: 4,069
25.11.2023, 15:13 4
Ещё раз посмотрел скриншоты - там какой-то хак с переменной r_mdData. При обращении к этой переменной генерится код mov eax,[ebp+8].

В итоге если не смотреть на исходный pascal-код можно подумать, что процедура _Test_LocalVars объявлена так:
Delphi
1
2
3
4
procedure _Test_LocalVars(var r_mdData);cdecl;
begin
...
end;
Может исходники не соответствуют бинарникам?
0
0 / 0 / 1
Регистрация: 09.10.2017
Сообщений: 27
25.11.2023, 16:13  [ТС] 5
Да нет, это не хак. Это странная манера Delphi работать с локальными переменными. Когда компилятору нужно получить доступ к переменным (или аргументам) родительской процедуры, он делает двойное разыменование регистра EBP: при первом разыменовании он получает адрес ячейки в стеке, в которой хранится значение регистра EBP для контекста родительской процедуры; при втором разыменовании компилятор получает доступ уже к самим переменным (аргументам) родительской процедуры. Если нужен доступ к переменным прародительской процедуры (т.е. на два уровня выше), Delphi выполняет тройное разыменование регистра EBP и т.д.
0
1485 / 1412 / 240
Регистрация: 19.02.2010
Сообщений: 3,912
25.11.2023, 18:12 6
Цитата Сообщение от GSV4 Посмотреть сообщение
И вообще, непонятно, зачем функция _Test_LocalVars формирует стековый кадр (сохраняет в стеке регистр EBP), ведь у нее нет ни аргументов, ни локальных переменных.
Галка Stack frames в настройках проекта, видимо, включена.
1
0 / 0 / 1
Регистрация: 09.10.2017
Сообщений: 27
25.11.2023, 19:03  [ТС] 7
Галка Stack frames в настройках проекта, видимо, включена.
Эта галка снята (см. скриншот 3 в первом посте), но в справке Delphi написано:

Некоторые инструменты отладки требуют, чтобы фреймы стека генерировались для всех процедур и функций, но в остальном у вас никогда не должно возникнуть необходимости использовать состояние {$W+}.
Миниатюры
Команды push EBP и pop ECX при вызове процедуры  
0
4164 / 1816 / 216
Регистрация: 06.10.2010
Сообщений: 4,069
26.11.2023, 10:41 8
Цитата Сообщение от GSV4 Посмотреть сообщение
Да нет, это не хак. Это странная манера Delphi работать с локальными переменными.
Извиняюсь - не заметил, что всё это вложено в процедуру Test_LocalVars_06c, подумал, что это глобальная переменная. Тогда получается, что для вложенных функций Delphi передаёт скрытый параметр - указатель на начало блока локальных переменных родительской процедуры по соглашению cdecl?
1
0 / 0 / 1
Регистрация: 09.10.2017
Сообщений: 27
26.11.2023, 19:16  [ТС] 9
Цитата Сообщение от murderer Посмотреть сообщение
Тогда получается, что для вложенных функций Delphi передаёт скрытый параметр - указатель на начало блока локальных переменных родительской процедуры по соглашению cdecl?
А почему именно по соглашению cdecl? Здесь везде соглашение pascal.

Ну вроде всё прояснилось:
1. Delphi для вложенной процедуры, образно говоря, пробрасывает мост, чтобы та могла получить доступ к ее данным.
2. А то, что при вызове вложенной процедуры регистр EBP сохраняется дважды (сначала перед вызовом процедуры, а потом самой процедурой), так это просто издержки режима отладки: вторая "копия" регистра EBP делается независимо от первой, т.к. используется только для отладки программы.
0
26.11.2023, 19:16
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.11.2023, 19:16
Помогаю со студенческими работами здесь

push и pop
У меня возникла странная проблема. Мы создали сайт на основе системы управления, которой...

Функции pop и push
Здравствуйте, есть код, решающий задачу. В нем есть стандартные функции push и pop. Как можно...

Верна ли реализация push/pop?
Правильный ли у меня ход мыслей при написании кода, на тему реализации стека? #include <stdio.h>...

PUSH/POP vs MOV из памяти
Какой из двух ниже перечисленных примеров занимает меньше процессорного времени (тактов) ? 1:...

Работа с push/pop в стеке
Здравствуйте, я тут столкнулся с проблемой, не могу понять, как работать со стеком. Ниже приведу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru