Форум: "Основная";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];
ВнизКак выделить область в стеке? Найти похожие ветки
← →
HydraMarat (2005-02-22 17:32) [0]Есть ли какая-нибудь функция типа GetMem для стека? Или это в принципе невозможно? Видел в модуле Grids.pas функцию StackAlloc вроде как "декрементирует" SP, но "глобально" она конечно же не работает, только в пределах одной подпрограммы (ну и видимо без вызовов других). Вот, например, C++ умеет же размещать в стеке объекты. Я понимаю, что это на уровне компилятора, но КАК-то же это делается. Может хоть ссылочку на подобное более детальную инфу дадите?
Спасибо.
← →
Anatoly Podgoretsky © (2005-02-22 17:49) [1]var внутри процедуры
← →
HydraMarat (2005-02-22 17:57) [2]Причем здесь var? Мне нужно сделать это глобально и иметь над этим контроль. Ну представим что нужно написать частичку C-компилятора. Или Вы имеете ввиду выделить статически в файле проекта большой объем (через var) и использовать его?
← →
Anatoly Podgoretsky © (2005-02-22 17:59) [3]При том, что память будет выделена на стеке и соответствует твоему вопрос, а про статику ты ничего не говорил
← →
HydraMarat (2005-02-22 18:08) [4]Упс, про файл проекта я загнался, процедур-то там нет, да и со "статико-динамикой" всё запутал.
В-общем главное в вопросе: аналог GetMem/FreeMem для стека. А может это как-то на asm"е делается?
← →
Amoeba © (2005-02-22 18:20) [5]А зачем, если сие не есть государственная тайна, это нужно?
← →
Набережных С. © (2005-02-22 18:29) [6]
> HydraMarat (22.02.05 18:08) [4]
> В-общем главное в вопросе: аналог GetMem/FreeMem для стека.
Это настолько бред, что даже возразить трудно:). В стеке переменные размещаются как раз для того, чтобы при выходе из функции не заботиться об освобождении памяти под них. Почитал бы какую-нибудь книжку про устройство компьютеров, что-ли...
← →
HydraMarat (2005-02-22 18:36) [7]Набережных С.
Да уж тебе точно возразить нечего... Не понял вопроса - не хрен отвечать.
← →
HydraMarat (2005-02-22 18:40) [8]Мне не нужно ИСПОЛЬЗОВАТЬ "уникальные возможности стека по освобождению памяти", мне надо СДЕЛАТЬ их. Для вызова системных функций и т.п.
← →
Amoeba © (2005-02-22 18:41) [9]
> HydraMarat (22.02.05 18:36) [7]
> Набережных С.
>
> Да уж тебе точно возразить нечего... Не понял вопроса -
> не хрен отвечать.
LMD!!!
← →
Amoeba © (2005-02-22 18:42) [10]
> HydraMarat (22.02.05 18:40) [8]
> Мне не нужно ИСПОЛЬЗОВАТЬ "уникальные возможности стека
> по освобождению памяти", мне надо СДЕЛАТЬ их. Для вызова
> системных функций и т.п.
Что-то орехами запахло...
← →
Набережных С. © (2005-02-22 18:43) [11]Совсем плохо дело:(
← →
HydraMarat (2005-02-22 18:47) [12]Ну чем оно плохо-то? Представьте что пишется интерпретатор, вот он считывает код, где пользователь вызывает функцию API. Как интерпретатор передаст ей параметры?
Если я чего-то не понимаю объясните!
← →
Набережных С. © (2005-02-22 18:55) [13]
> HydraMarat (22.02.05 18:47) [12]
> Как интерпретатор передаст ей параметры?
Зависит от соглашения о передаче параметров. Может через регистры, а может через стек. В последнем случае для размещения параметров в стеке используются инструкции процессора Push.
Видишь ли, очень грубо говоря, разные функции для своих параметров используют одни и те-же ячейки стека, и в том месте, где для одной расположена переменная А: integer, для другой может находиться B: double. Чтобы понимать всю эту кухню нужно представлять устройство процессора хотя-бы в общих чертах.
← →
HydraMarat (2005-02-22 18:59) [14]Поясню на примере кода, я уж начинаю думать что вопрос "не из той оперы". Например, юзер написал:
function F(A, B: Integer): Double; lib "Lib" name "Name"
Интерпретатор (который пишется мною) встречает вызов: F(3, 4); Он загружает Lib, находит адрес Name, теперь ей надо передать параметры, и вызвать. Как это осуществить?
← →
Набережных С. © (2005-02-22 19:09) [15]
> Как это осуществить?
Для начала выучить ассемблер.
Ты так ничего и не понял:( Все, я иссяк...
← →
Юрий Зотов © (2005-02-22 19:31) [16]> HydraMarat (22.02.05 18:59) [14]
> Интерпретатор (который пишется мною) встречает вызов: F(3, 4);
> Он загружает Lib, находит адрес Name, теперь ей надо передать
> параметры, и вызвать. Как это осуществить?
На псевдоассемблере (чтобы был понятен механизм):
push 3
push 4
call F
В реальности - чуть сложнее, с учетом соглашений о вызове и пр., но схема та же.
И не нужны никакие стековые GetMem. Потому что иначе терятся сам смысл стека.
← →
HydraMarat (2005-02-22 21:04) [17]
> Набережных С.
Иссяк? Вы так ничего и не ответили на мой вопрос.
> Юрий Зотов
Про PUSH и POP я знаю... И что? Я же сказал: интерпретатор не знает заранее что и как, т.е. изначально я эти инструкции прописать не смогу. Или мне в цикле?
for I := 0 to ParamCount - 1 do
asm
PUSH Params[I]
end;
a потом:
asm
CALL Lib.Name
end;
где Lib.Name - адрес полученный через GetProcAddress?
И давайте без стёба. Считаете что глупость - объясните почему. Считатете что самые умные - ответьте на вопрос.
← →
Набережных С. © (2005-02-22 21:07) [18]
> HydraMarat (22.02.05 21:04) [17]
Да где уж мне:(
← →
HydraMarat (2005-02-22 21:08) [19]Да и еще. Прочел вот про инструкции ENTER и LEAVE. Правильно ли я понял что это и есть то о чем я спросил? Через ENTER выделил, через LEAVE убрал все нафиг... это я про локальные переменные, а не про вызовы...
← →
HydraMarat (2005-02-22 21:11) [20]
> Набережных С.
Ну ответьте что не так? Как бы Вы осуществили такие действия? Ну и соглашение пусть будет __cdecl
← →
Petr V. Abramov © (2005-02-22 21:12) [21]> Или мне в цикле?
В принципе лучше сам цикл на ассемблере написать. А что в этом цикле писать - посмотрите в окне cpu код, который генерирует Delphi и почитайте по соглашения о вызовах.
← →
HydraMarat (2005-02-22 21:28) [22]
> Набережных С.
Может Вы все-таки ответите на мой вопрос? По-подробнее... Я же просто хочу понять в чем я не прав. Я пришел сюда получить ответ.
> Petr V. Abramov
Гм, да CPU View надо посмотреть.
← →
begin...end © (2005-02-22 21:32) [23]> HydraMarat (22.02.05 21:04) [17]
> Я же сказал: интерпретатор не знает заранее что и как
Интерпретатор должен определить число параметров и запихнуть все параметры в стек или передать параметры через регистры (в случае, если параметров немного). Передать можно по ссылке или по значению - в первом случае запихиваются адреса параметров, во втором - значения параметров. Далее идёт вызов нужной подпрограммы (CALL). Если эта процедура уже написана, то Вам нужно знать, откуда она читает параметры - из стека, из регистров или ещё как-то. Должно быть также известно соглашение о порядке передачи параметров.
Что же касается команд ENTER и LEAVE, то они пишутся внутри подпрограммы. Предназначены они для облегчения написания кода пролога/эпилога и автоматически заталкивают/извлекают в/из стека содержимое некоторых регистров.
← →
HydraMarat (2005-02-22 21:49) [24]
> begin...end
А вот тот код про PUSH в цикле (допустим соглашение - всё через стек) сработает? И вроде PUSH/POP работает с 16 и 32 битным операндами. Тогда как же по-значению передавать операнды больших размеров? Или их строго через указатели?
> Что же касается команд ENTER и LEAVE, то они пишутся внутри
> подпрограммы. Предназначены они для облегчения написания
> кода пролога/эпилога и автоматически заталкивают/извлекают
> в/из стека содержимое некоторых регистров.
Можно подробнее? Или мне лучше за "чтиво" взяться?
← →
Набережных С. © (2005-02-22 21:50) [25]
> HydraMarat (22.02.05 21:28) [22]
> Я пришел сюда получить ответ.
А я пришел сюда, чтобы, кроме прочего, давать ответы...если у меня возникнет такое желание. Вот Вам отвечать у меня сначала желание было, а потом пропало, уж извините. Но Вы не расстраивайтесь, здесь бывает много грамотных людей, кто-нибудь да поможет. Да уже и помогают.
← →
HydraMarat (2005-02-22 22:02) [26]
> Набережных С.
И что же Вас оттолкнуло?
← →
begin...end © (2005-02-22 22:12) [27]> HydraMarat (22.02.05 21:49) [24]
> Тогда как же по-значению передавать операнды больших
> размеров?
Ответ очевиден - либо указатели, либо значения по частям.
> Можно подробнее? Или мне лучше за "чтиво" взяться?
Вкратце - LEAVE/ENTER сохраняют/восстанавливают важные регистры (типа EBP) в стеке. За "чтиво" взяться нужно обязательно.
← →
begin...end © (2005-02-22 22:17) [28]> begin...end © (22.02.05 22:12) [27]
> LEAVE/ENTER сохраняют/восстанавливают
ENTER/LEAVE сохраняют/восстанавливают
← →
HydraMarat (2005-02-22 22:18) [29]Ладно, "накачал" кучу статеек, видно не все так просто как хотелось (предполагалось). Буду читать, если что назреет - напишу.
Всем спасибо.
← →
Fay © (2005-02-23 03:02) [30]2 begin...end © (22.02.05 22:17) [28]
...LEAVE/ENTER/LEAVE... ... восстанавливают/сохраняют/восстанавливают...
8)
← →
Германн © (2005-02-23 03:25) [31]2 HydraMarat
Для начала вернись,хотя бы на
HydraMarat (22.02.05 18:59) [14]
И просмотри еще раз два последущих поста [15] и [16].
И еще раз подумай, если сможешь!
← →
HydraMarat (2005-02-23 11:58) [32]
> Германн
Ну подумал и че? Если Вы считаете, что ответ "выучить ассемблер" то, что мне надо, то... Ну давайте большинству спрашивающих отвечать "выучить Delphi"!
Интересно, я посмотрел внимательнее Grids.pas фукнцию StackAlloc и процедурку StackFree... и написано:
{ StackAlloc allocates a "small" block of memory from the stack by decrementing SP. This provides the allocation speed of a local variable, but the runtime size flexibility of heap allocated memory. }
А потом почитал про то, что "выделение памяти в стеке" - это уменьшение этого самого SP (ESP). Посмотрел CPU View - параметры функцияи API передаются через стек (по крайней мере у тех, что я смотрел). Нельзя было этим ответить? Или Вы все только буквально понимаете? Нельзя привести пример вызова на ассмеблере?
← →
HydraMarat (2005-02-23 12:02) [33]Есть еще вопросик: что означает выраванивание по словам, байтам, двойным словам и т.п. В чем суть? Мне когда-то объясняли, но я с этим не работаю и все время забываю. Объясните, плиз, если не сложно (уф) ...
← →
Anatoly Podgoretsky © (2005-02-23 12:07) [34]Это означает выравнивание на границу слова, байта, двойного слова и т.д.
← →
HydraMarat (2005-02-23 12:10) [35]
> Anatoly Podgoretsky
Как это на цифрах сказывается?
← →
Anatoly Podgoretsky © (2005-02-23 12:13) [36]1, 2, 4, и т.д.
← →
HydraMarat (2005-02-23 12:20) [37]
> Anatoly Podgoretsky
В комментариях к StackAlloc написано: "round up to keep ESP dword aligned". Это делается для того, чтоб ESP всегда был четным? (кстати, получаемые цифирки кратны 4)
← →
begin...end © (2005-02-23 12:53) [38]> HydraMarat (23.02.05 11:58) [32]
> Посмотрел CPU View - параметры функцияи API передаются
> через стек (по крайней мере у тех, что я смотрел).
Да, так и есть. Причём в обратном порядке - вначале последний параметр, потом предпоследний и т.д.
> Нельзя было этим ответить?
Так Вам же и сообщили, что это один из способов передачи параметров. Что не так? Про API-функции, для которых этот способ является традиционным, до этого Вашего поста речи не было.
> Нельзя привести пример вызова на ассмеблере?
Пример (абстрактный) уже дали в [16]. Хотите неабстрактный - пожалуйста. Вот пример вызова API-функции CopyFile:var
S1, S2: PChar;
begin
S1 := "C:\test.txt"; // Имя файла-источника
S2 := "D:\test.txt"; // Имя файла-приёмника
// BOOL CopyFile(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, BOOL bFailIfExists)
asm
// Передаём параметр bFailIfExists
PUSH $00
// Передаём параметр lpNewFileName
PUSH S2
// Передаём параметр lpExistingFileName
PUSH S1
// Вызываем функцию
CALL CopyFile
... // Анализируем результат функции (она помещает его в EAX)
end
...
end.
P.S. И давайте это... как-то поспокойнее, что ли...
← →
begin...end © (2005-02-23 13:11) [39]> HydraMarat (23.02.05 11:58) [32]
> А потом почитал про то, что "выделение памяти в стеке"
> - это уменьшение этого самого SP (ESP).
Да никакое это не выделение памяти, понимаете? Размер стека фиксирован. Для помещения в стек какого-нибудь параметра - например, размером в слово, - указатель вершины стека SP/ESP уменьшается на 2. Если размер параметра равен 4 байтам (двойное слово), то SP/ESP уменьшается на 4. И потом помещаемое значение записывается по адресу SS:ESP. Вот и всё. Но размер стека от этого не меняется.
А в вызываемой процедуре можно потом получать доступ к тем параметрам, которые были засунуты в стек вызывающей программой. Как это делать - это уже Ваше дело. Либо забирать их оттуда, либо использовать регистр базы кадра стека EBP. Но не забывать при этом написать в процедуре нормальный код пролога/эпилога.
← →
HydraMarat (2005-02-23 13:30) [40]
> begin...end
К Вам у меня, кстати, претензий нет, от Вас ответ я получил. Ну ладно, к черту все это, никого обидеть не хотел.
По существу. "Выделение памяти" я взял в кавычки, но не исключаю, что вопрос был не совсем корректно сформулирован. Однако, я не писал о размере стека, я писал о резервировании в нем места. Никто же не говорит, что GetMem, образно выражаясь, изменяет физический объем оперативной памяти. Ну и это к черту.
Совсем по существу. Побаловался с ENTER/LEAVE - работает как надо. Набрались еще вопросы, часть может повторится. Можно ответить просто да/нет:
1) Локальные переменные обычно размещают в стеке?
2) Почему параметры для API через стек, а результат в EAX? Это соглашение?
3) Delphi"иские подпрограммы используют __fastcall?
4) Допустим мой интерпретатор тока-тока запускает программу. Могу ли я зарезервировать место в стеке (уменьшить ESP) заранее и просто адресовать его во всех подрограммах, а при их переключениях просто менять содержимое? Для МОИХ естественно данных, а не того что Delphi"ийский компилятор сделает.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.066 c