Форум: "Основная";
Текущий архив: 2003.07.03;
Скачать: [xml.tar.bz2];
ВнизВопрос по Стэку и все что с ним связано. Найти похожие ветки
← →
Doc (2003-06-20 13:07) [0]Подскажите пожалуйста, когда стэк начинает разростаться, при каждом последующем помещении
переменных в стэк адрес стэка возрастает или уменьшается?
Логически кажется, что должен увеличиваться.
Хотя встретил пример, там приводиться следующая структура
Before push(eax)
____$00FF_FFFF
____$00FF_FFFE
____$00FF_FFFD
____$00FF_FFFC
____$00FF_FFFB
____$00FF_FFFA
____//
____$00FF_FFE9
____$00FF_FFE8
=> ESP
____$00FF_FFE7
____$00FF_FFE6
____$00FF_FFE5
____$00FF_FFE4
____$00FF_FFE3
____$00FF_FFE2
After push(eax)
____$00FF_FFFF
____$00FF_FFFE
____$00FF_FFFD
____$00FF_FFFC
____$00FF_FFFB
____$00FF_FFFA
____//
____$00FF_FFE9
____$00FF_FFE8
____$00FF_FFE7
____$00FF_FFE6
____$00FF_FFE5
=> ESP
____$00FF_FFE4
____$00FF_FFE3
____$00FF_FFE2
Вообще где можно подробней узнать о структуре стэка поподробнеe.
← →
delphimun (2003-06-20 13:35) [1]Почитай Асемблер учебный курс автор В.Ю.Пирогов (там вроде вначале книги про стек подробно написано) или найди уроки обучения Ассемберу там везде про стек очень подробно расписано(что где как да почему)
← →
Федя (2003-06-20 13:53) [2]Адрес стека уменьшается.
Это было сделанно в архитектуре i86 для программы у которых cs=ds=ss. Так-как стек растет на встречу куче то sp уменьшается
← →
Anatoly Podgoretsky (2003-06-20 14:08) [3]Про какой конкретно стек идет речь, это чисто логическая стуруктура в одним концои, где реализация может быть любая и не обязательно адресная.
← →
Digitman (2003-06-20 14:13) [4]
> Doc
адрес вершины стека (содержимое регистра [e]sp) всегда уменьшается при помещении на вершину стека очер.значения (в результате явных или неявных операций со стеком)
> Федя
> Это было сделанно в архитектуре i86 для программы у которых
> cs=ds=ss
совершенно не факт.
ибо никакой связи между стековым механизмом как таковым и конкретными значениями сег.регистров в архитектуре i80x86 нет.
> стек растет на встречу куче то sp уменьшается
[e]sp уменьшанется ВНЕ зависимости от опер.системы.
понятие же "куча" имеет определенный смысл лишь в ОС на базе Win32.
в ДОС понятия "куча" не было (несмотря на некоторое, весьма и весьма отдаленное сходство механизмов программных менеджеров памяти), однако стек там как рос вниз, так и по сей день растет)
← →
Федя (2003-06-20 14:32) [5]2Digitman
>>[e]sp уменьшанется ВНЕ зависимости от опер.системы.
А кто говорил про ОС
>>в ДОС понятия "куча" не было
:)))
← →
Федя (2003-06-20 14:33) [6]2Digitman
>>[e]sp уменьшанется ВНЕ зависимости от опер.системы.
А кто говорил про ОС
>>в ДОС понятия "куча" не было
:)))
>>однако стек там как рос вниз, так и по сей день растет)
а кто говорит что вверх?
← →
Digitman (2003-06-20 14:41) [7]
> Федя
> А кто говорил про ОС
а кто упомянул термин "куча" ?)
а "как прикажешь понимать тебя, Саид", если в то время как речь идет исключительно о концепции стекового механизма, ты оперируешь термином, не имеющим ничего общего с концепцией , а относящимся как минимум к одной конкретной ОС-платформе ?
))
← →
Doc (2003-06-20 14:44) [8]Я тут покапался в коде, тоже в принципе понял, что
Push уменьшает указатель стэка, а pop его увеличивает.
Вот такой вопрос возник.
Если у нас максимальный размер стэка $00100000
То при вызове процедуры, в которой в var будет 10 элементов массива типа integer, программа создаст стэк, у которого верхний адрес будет текущая позиция + 10*4 байт или $28, т.е.
и постепенно будет опускаться вниз. Адрес вершины стека окажеться
текущий адрес+$01, а самый последний элемент, который затолкали первым, будет по адресу (текущий адрес+$28).
Я правильно понимаю или у меня что-то с головой?
А еще вопрос.
Если мы динамически создаем массив, то я так понял будет просто выделено место для нашей процедуры,
текущий адрес + $100000, а дальше что нам нужно, то мы с этим местом и делаем, но эти адреса я так понял уже будут зарезервированы? или динамически все по другому происходит?
Господа проясните плиз...
← →
Doc (2003-06-20 14:46) [9]
> Anatoly Podgoretsky © (20.06.03 14:08)
> Про какой конкретно стек идет речь, это чисто логическая
> стуруктура в одним концои, где реализация может быть любая
> и не обязательно адресная.
Меня больше интересует адресная реализация.
Про логическую структуру LIFO я знаю.
← →
Digitman (2003-06-20 14:54) [10]
> Doc
ты учитываешь, что при вызове процедуры на вершину стека помещается :
- фактические параметры процедуры (по необходимости. в зависимости от calling convention);
- адрес возврата - в win32 = 4 байта (обязательно);
??
← →
Doc (2003-06-20 15:44) [11]
> ты учитываешь, что при вызове процедуры на вершину стека
> помещается :
>
> - фактические параметры процедуры (по необходимости. в зависимости
> от calling convention);
> - адрес возврата - в win32 = 4 байта (обязательно);
>
> ??
Да, ну и когда все укладывается в вершину стэка,
Параметры процедуры, ret
Размер стэка для каждой процедуры, насколько я понял урезается статически, на столько на сколько требуется.
Т.е. если Max Stack size $100000
При статической компиляции, если потребуется $0000FF, то столько и будет выделено, т.е. структура стэка в данном случае будет не $100000, а меньше.
Тогда почему когда мы создаем огромный массив, сразу компилятор не выдает ошибки, типа StackOverflow, а только когда уже программа выполняется? Если все заталкивается в стэк еще при статической компоновке.
А как происходит в случае если массив создается динамически и неизвестно, сколько будет у него элементов.
Я так понимаю что программа выделяет область памяти для стэка в
$100000 по умолчанию, и если она будет занята допустим на
After push(eax)
____$00FF_FFFF
____$00FF_FFFE
____$00FF_FFFD
____$00FF_FFFC
____$00FF_FFFB
____$00FF_FFFA
____//
____$00FF_FFE9
____$00FF_FFE8
____$00FF_FFE7
____$00FF_FFE6
____$00FF_FFE5
=> ESP
____$00FF_FFE4
____$00FF_FFE3
____$00FF_FFE2
То это уже наша проблема, теряем часть памяти?
И если заполняя уже этот по умолчанию стэк размером $100000
лимит 64K будет привышен, то и с нашим динамическим массивом будет StackOverflow, или динамические массивы как то иначе линкуются и StackOverflow уже невозможен, а возможна нехватка памяти.
Если вы поняли, что я имел ввиду, проясните пожалуйста.
← →
Anatoly Podgoretsky (2003-06-20 15:50) [12]Адресная реализация делается так, при Push: Pointer +(-) на размер стека элемента, при Pop: Pointer -(+) на размер стека элемента. Стем создается статически или динамически.
← →
Digitman (2003-06-20 15:54) [13]
> Doc
> почему когда мы создаем огромный массив, сразу компилятор
> не выдает ошибки, типа StackOverflow, а только когда уже
> программа выполняется? Если все заталкивается в стэк еще
> при статической компоновке.
вот именно ! при компоновке ! а не при компиляции)
компилятор, зная о размере лок.переменных п/программ, ничего не знает о будущем размере стека, а линкер, зная о требуемом MaxStackSize, ничего не знает о том, каким какие маш.инструкции, созданные компилятором, в каком порядке и как будут использовать будущий стек)
← →
Digitman (2003-06-20 16:11) [14]
> все заталкивается в стэк еще
> > при статической компоновке.
неговори ерунды
фрейм стека для размещения лок.данных п/программы создается динамически, в run-time
обычно в Паскале это делается так :
push ebp
mov ebp, esp
sub esp, размер_фрейма // создаем фрейм
... здесь обращаемся к лок.переменным по смещению во фрейме [ebp - смещение_переменной]
... или обращаемся к параметрам п/программы, если они передавалисть через стек [ebp + размер_адреса_возврата + смещение_параметра]
add esp, размер_фрейма //уничтожаем фрейм
pop ebp
в некоторых компиляторах (особенно - ранних версий) вместо манипуляций с esp и ebp для той же цели применяется пара инструкций enter/leave, но она менее эффективна по производительности и далеко не всегда оптимальна.
← →
Doc (2003-06-20 18:50) [15]Большое спасибо, с этим разобрался.
Еще вопрос.
При объявлении массива
var Arr:array[1..500] of integer;
i:integer;
begin
for i:=1 to High(Arr) do begin arr[i]:=10; end;
end;
При breakpoint"e установленном на begin, выполняется команда
add esp, $fffff830 и сразу
переходит к циклу for i:=....
А вот если массив например
var Arr:array[1..25000] of integer;
i:integer;
begin
for i:=1 to High(Arr) do begin arr[i]:=10; end;
end;
То на breakpoint"e на begin"e прокручивается цикл и несколько команд
push eax
mov eax, $00000018
add esp,$fffff004
push eax
dec eax
jnz -$0a
mov eax,[esp+$00018000]
add esp,$fffff964
и уже потом идет for i:=....
Кто-нибудь может прокоментировать, что происходит в цикле?
Насколько я понял небольшими кусками выделяются адреса памяти
0012E5AC, а потом EAX $00000017 и уже
0012D5AC, что составляет разницу
$1000 или 4096
Откуда это взялось, объясните пожалуйста, почему не может быть все сделано сразу,
за один проход, как в первом случае, и что 4096 за число такое.
← →
Doc (2003-06-20 20:40) [16]И еще, можно ли 4096, как то регулировать?
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2003.07.03;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.009 c