как динамически выделить память для массива в сборке 8086 с помощью nasm

Так что мне нужно сделать что-то подобное в сборке

int *arr = malloc(sizeof (int) * size);

где пользователь вводит размер, и в зависимости от размера будет вызываться цикл while для заполнения массива.

Итак, мне нужен указатель на пространство, созданное malloc, как мне это сделать в заднице 86? Кроме того, где мне хранить этот указатель, чтобы я мог использовать массив позже. Сказать сделать бинарный поиск на входе?

с уважением


person arif    schedule 06.04.2011    source источник
comment
Поскольку в нем отсутствует ОС, будь то 32/64-разрядная версия и т. д., а также какой-либо контекст в отношении области действия переменных. Для 32-разрядного кода Linux вы можете использовать sys_brk syscall для создания некоторого пространства. У меня есть [предыдущий ответ] на StackOverflow, который охватывает это: stackoverflow.com/a/33903235/3857942. Обычно в 32-битном Linux sys_brk используется для выделения базовой памяти, которую куча (используемая malloc) в конечном итоге будет использовать для разделения для удовлетворения запросов.   -  person Michael Petch    schedule 27.03.2016


Ответы (5)


Предположим, вы работаете под Win и создаете консольное приложение (в следующий раз дайте больше подробностей), решение, найденное в The Art Of Assembly Language (заглавными буквами, потому что это замечательная книга):

13.3.6.1 Выделение памяти

Function (ah):     48h  
Entry parameters:  bx- Requested block size (in paragraphs)  
Exit parameters:   If no error (carry clear):  
                       ax:0 points at allocated memory block  
                   If an error (carry set):  
                       bx- maximum possible allocation size  
                       ax- error code (7 or 8)  

This call is used to allocate a block of memory. On entry into DOS,
bx contains the size of the requested block in paragraphs (groups of
16 bytes). On exit, assuming no error, the ax register contains the
segment address of the start of the allocated block. If an error
occurs, the block is not allocated and the ax register is returned
containing the error code.  
If the allocation request failed due to insufficient memory, the bx 
register is returned containing the maximum number of paragraphs actually
available.

13.3.6.2 Освобождение памяти

Function (ah):    49h  
Entry parameters: es:0- Segment address of block to be deallocated  
Exit parameters:  If the carry is set, ax contains the error code (7,9)  

This call is used to deallocate memory allocated via function 48h above. The
es register cannot contain an arbitrary memory address. It must contain a
value returned by the allocate memory function. You cannot use this call to
deallocate a portion of an allocated block. The modify allocation function
is used for that operation.

13.3.6.3 Изменение распределения памяти

Function (ah):     4Ah
Entry parameters:  es:0- address of block to modify allocation size
                   bx- size of new block
Exit parameters:   If the carry is set, then ax contains the error code 7, 8,
                   or 9
                   bx contains the maximum size possible (if error 8)

This call is used to change the size of an allocated block. On entry, es must
contain the segment address of the allocated block returned by the memory
allocation function. Bx must contain the new size of this block in paragraphs.
While you can almost always reduce the size of a block, you cannot normally
increase the size of a block if other blocks have been allocated after the
block being modified. Keep this in mind when using this function.

страница 719, если вам это нужно ;)

person BlackBear    schedule 06.04.2011

Каким-то образом я собираюсь предположить, что это не то, что вы хотите сделать.

Просто выделить память в ассемблере не так-то просто.

Это легко сделать, если вы собираетесь вызывать системную функцию, если вам нужно понимать соглашения о вызовах для подпрограмм, библиотек и компоновщиков вашей операционной системы. Вы можете вызывать какую-то функцию ОС, возможно, через прерывание, и это, опять же, зависит от операционной системы.

Потому что обычно программы на ассемблере, как правило, имеют довольно статичное представление памяти и определяют свою собственную карту памяти. Вы можете выделить большой блок данных, а затем настроить свой собственный «malloc» для этого блока. Исходный блок станет вашим, когда подпрограмма загрузится. Это, вероятно, ближе к тому, что вы хотите сделать, но, очевидно, это может потребовать гораздо больше работы.

Если вы не выделяете одновременно более одного массива, просто определите блок в исходном коде сборки, который является «достаточно большим» (скажем, 10 000 целых чисел). Тогда вы можете просто использовать это.

Предполагая, что вы вызываете какую-то процедуру выделения памяти, результат будет возвращен либо в стек, либо в регистр. Затем вы либо оставите это значение в регистре, предназначенном для хранения его до конца вашей обработки, либо вы можете просто сохранить значение в памяти в другом месте, а затем загрузить его, когда оно вам понадобится позже.

person Will Hartung    schedule 06.04.2011

Вы можете вызвать malloc() непосредственно из своего ассемблерного кода. Действительно!

В этом руководстве показано, как это сделать. Не волнуйтесь, эта техника не ограничивается Mac OS X.

person karlphillip    schedule 06.04.2011

Если вам не нужно, чтобы выделение длилось за пределами текущей функции, просто выделите в стеке:

; calculate allocation size in eax, for example
sub   esp, eax
; esp points to the memory

Если это происходит в функции, а не на верхнем уровне, то функция должна использовать кадр стека (push ebp/mov ebp, esp, тело функции, leave/ret) для восстановления esp, чтобы вы могли pop свои другие регистры.

person Peter Cordes    schedule 27.03.2016

C компилируется в сборку, и сгенерированный ассемблерный код также вызывает malloc. sizeof(int) должен быть 4 байта/32 бита/двойное слово в x86.

person Guest    schedule 27.03.2016