Подскажите пожалуйста как в ассемблере динамически выделять память. Есть ли в ассемблере нечто аналогичное ключевому слову new в С++ ?
в ассемблере нет,есть API HeapAlloc выделяет память из кучи,VirtualAlloc резервирует память из адресного пространства процесса
2asmfan Стек не пойдет для динамической памяти, т.к в стеке выделяется память в пределах данной процедуры и после выхода из процедуры и уравнивания стека теряется если мы не передадим ее каким то образом. А если я выделяю память на большие массивы заранее неизвестной длины, то я считаю что все-таки нужно выделять память в другом месте, а в стеке хранить только указатель на нее. Гораздо удобнее передовать между функциями указатели чем сами данные огромных неизвестных заранее размеров.
Lightning Очень редко память выделяется "снизу вверх", то есть выделяя память в вызываемой функции и возвращая её вызывающей. Чаще наоборот, поэтому стек можно беспрепятственно использовать в качестве динамической памяти. Только позаботиться о непревышении его размера и выделять память постранично, чтобы не перепрыгнуть сторожевую страницу.
IceStudent ????????? Наверное, я ничего не понимаю! Может кто-нибудь поможет мне понять как можно выделить в стеке память в ВЫЗЫВАЕМОЙ функции так, чтобы потом она была доступна в ВЫЗЫВАЮЩЕЙ. Помогите пожалуйста....хотябы маленьким примерчиком кода...
А че не понимать то? ты же когда пишешь на асме ты же убийство стека выделенного под параметры сам можешь задать!!! Вот смотри: push arg1 call func на стеке будет: addr_ret,arg1 при возврате ты должен ret так? а это убийство addr_ret а память под arg1 как была так и есть, если ты делаешь stdcall то вызваемая ф-ция бьет этот параметр, если си-конвенцию, то после вызова ф-ции бьешь параметр для ф-ции. Вот и думай. В ф-ции сделал: sub esp,скоко надо памяти+ учитывай адрес возврата После вызова ф-ции call func стек не очищай, а только ret!!! И будет тебе счастье!
ds_punks Спасибо. Это я уже читал. EvilsInterrupt При большой вложености функций это как то страшно будет... Всем спасибо.
Lightning Напиши на асме аналог, назови его new и пусть он у тебя выделает, скоко надо! Если не через чур много будешь выделять, то стек самое то! НО! Представь ситуацию: int a = new int[1250]; int b= new char[123]; если ты через стек это будешь делать, то предположим a уже не надо и че тогда? Просто так память с кушало? Если да то надо удалить, а как, если она выделялась первой?
EvilsInterrupt Вот именно. Ты прав. Так что наверное лучше юзать API функции для работы с памятью... а жаль.
Lightning > выделить в стеке память в ВЫЗЫВАЕМОЙ функции так, чтобы потом она была доступна в ВЫЗЫВАЮЩЕЙ. Вот это и надо было сказать сразу. Теоретически можно, как написал EvilsInterrupt, но рискованно. Иначе - только API + можно написать свой менеджер памяти.
IceStudent Я уже понял что лучше использовать API. Еще я подумал что можно определить в программе дополнительный сегмент памяти нужного размера и сделать в нем нечто на подобии кучи. В начале него хранить структуру данных о свободной памяти и написать пару функции для управления и распределения памяти. В принципе это и получится свой менеджер памяти внутри программы.
IceStudent Раз уж стека коснулись спрошу: В PE-заголовки указаны сколько проге надо стеку вообще, и сколько в самом начале! Что если прога возьмет и сделает: sub esp,большое число где: большое число укладывающееся в число сколько можно выделеить под стек вообще, но больше числа которое выделено под стек при инициализации процесса. что произойдет? Я полагаю исключение какое-нить, чтобы стек добавить, так? Теперь дам определения: кусок памяти добавляемый к памяти текущего стека, назову - странице стека ( т.к. не знаю как обычно в доках это называют) и стартовый размер куска памяти выделяемый под стек процессу - начальная страница стека. Всего процессу позволено иметь n страниц стека и определяется размер в PE-заголовке. что если в программе сделать: sub esp,digit где: digit = (размер страницы стека * m) и digit < n страниц стека что будет? Каковы действия системы?
Lightning Code (Text): HeapCreate(HEAP_NO_SERIALIZE,0,0); Потом можешь выделить из этой кучи сколько угодно байт, пока физ. память не кончится.
EvilsInterrupt За резервирование и выделение в link.exe /STACK: COMMIT, RESERVE... да сам погляди попробуй залинкуй с опциями 10,10 и засубь есп в программею чё получится не знаю. но походу она вся сколько бы ты не закозал не инициализирована (странички чистые). Вот замечал когда из глубокой рекурсии выходишь память не полностью восстанавливается - странички грязные потому что. да и про остальную динамическую память актуально - когда странички чистые - не в оперетиве значит, а тока в уме ядра.
EvilsInterrupt > В PE-заголовки указаны сколько проге надо стеку вообще, и сколько в самом начале! Точнее, сколько зарезервировано памяти под стек и сколько из неё выделено (см. VirtualAlloc). > Я полагаю исключение какое-нить, чтобы стек добавить, так? Это если не проскочишь сторожевую страницу. Иначе - обычный AV со всеми вытекающими. На форуме обсуждалось, кстати - ищи в постах leo Поэтому vc++ вставляет служебную функцию, выделяющую большие куски памяти в стеке и "пробующую на запись" каждую страницу, чтобы система подкачала невыделенные страницы стека.
Почему про GlobalAlloc забыли? push BuffSize push GMEM_FIXED ; не будем менять размер буффера - подробности в msdn call GlobalAlloc mov hBuff, eax ; .... ; получили буфер размера BuffSize, делаем с ним что хотим - пишем, читаем.. ; ... push hBuff call GlobalFree тут надо отметить, что размер буфера не равен в точности BuffSize - он округляется в большую сторону до 512 байт (или килобайта или ококло того), потому при работе со списками бывает выгодно выделить большой буфер и помещать в него несколько элементов