Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-1108806190
netmouse
2005-02-19 12:43
2005.03.06
DBGrid


1-1108972403
Sour Smile
2005-02-21 10:53
2005.03.06
Как освободить ресурсы занятые функцией StringToOleStr?


1-1109234508
Brain Force
2005-02-24 11:41
2005.03.06
Как получить текущую позицию курсора мыши


3-1107855118
Sava
2005-02-08 12:31
2005.03.06
Хранения изображений в БД


3-1107529765
denis24
2005-02-04 18:09
2005.03.06
select ...blob-поля + count() ...group by





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский