Сборка: динамическое выделение памяти без malloc и syscalls?[Приложение FreeDOS] - PullRequest
3 голосов
/ 28 июня 2019

Мой вопрос касается логики динамического выделения памяти в сборке (в частности, MASM). Есть много статей на эту тему, и все они основаны на использовании malloc или brk. Однако, как я понимаю, malloc как часть языка C обязательно (или может) быть написан на ассемблере. Идеально для brk, потому что это часть операционной системы, поэтому он также написан на C, который можно заменить 1 на 1 сборкой. Очень давно я видел статью в PCMag о динамическом распределении памяти в MS-DOS с использованием чистого asm. К сожалению, я потерял все следы этого замечательного произведения. Сейчас я работаю с FreeDOS (точно загружаемая флешка FreeDOS) и задаюсь вопросом, как поступить, если кто-то решит написать свой собственный распределитель памяти? Какова отправная точка и логика распределения памяти без использования механизмов ОС?

1 Ответ

6 голосов
/ 28 июня 2019

Когда DOS загружает программу .COM, она распределяет всю память, доступную в области 640 КБ (ниже 0a000h: 00000h), и программа может управлять своей собственной памятью. Если необходимо использовать управление памятью MSDOS, программа сначала должна освободить память, используя INT 21H, AH=49H, ES=segment, BX=# paragraphs. Затем он может использовать INT 21H, AH=48H, BX=# paragraphs для выделения памяти.

Как отмечается в комментариях, программа .EXE может выделять или не распределять всю память в области 640 КБ.

Пример кода сборки .COM для освобождения, а затем для выделения всей доступной памяти. MSDOS обычно потребляет 16 байтов для своих служебных данных. В этом примере BX устанавливается в конец кода, а затем устанавливается в границу следующего абзаца, которая составляет 256 байт после конца кода, чтобы использовать его в качестве стекового пространства. Конец этого стека является базой памяти, освобожденной вызовом INT 21H, AH=4AH.

        .286
        .model  tiny,c
        .code
        org     0100h
;       cs,ds,es,ss = program segment prefix, sp = 0fffeh
start:  mov     bx,offset cdend         ;set bx=end stack
        add     bx,0010fh
        and     bx,0fff0h
        mov     sp,bx                   ;sp = new end of stack
        mov     cl,4                    ;release memory
        shr     bx,cl
        mov     ax,04a00h
        int     21h
        mov     ax,04800h               ;set bx = available memory
        mov     bx,0ffffh
        int     21h
        mov     ax,04800h               ;allocate all of it
        int     21h                     ; returns segment in ax
exit:   mov     ax,04c00h               ;exit
        int     21h
cdend:
        end     start
...