Вниз
Скачать: CL | DM;

Вопрос по Стэку и все что с ним связано.   Найти похожие ветки 

← →
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 вся ветка

Скачать: CL | DM;



Память: 0.5 MB
Время: 0.011 c
9-7283
MRB_SPB
2003-01-15 18:16
2003.07.03
PlayStation2


1-7433
stalker780
2003-06-23 13:32
2003.07.03
DevEx QGrid 4 и Bar 4 в DLL


7-7738
anton_cor
2003-04-22 15:31
2003.07.03
Как получить список процессов из консольного или не имеющего окна


3-7290
Alek Aaz
2003-06-04 12:10
2003.07.03
Table is busy


14-7658
INTAARI
2003-06-16 18:42
2003.07.03
Где можно взять WinSocket 2.0 и DCOM




   Наверх