Search code examples
assemblydosheap-memorydynamic-memory-allocationx86-16

Assembly: dynamic memory allocation without malloc and syscalls? [FreeDOS application]


My question is about the logic of dynamic memory allocation in assembly (particularly, MASM). There are lot of articles on this topic and all of them rely on the use of malloc or brk. However, according to my understanding, malloc as a part of C language must (or could) be certainly written on assembly. Idem for brk, because it's a part of the operating system, thus also written on C which can be replaced 1 to 1 by assembly. Very very long time ago I have seen an article in PCMag about dynamic memory allocation in MS-DOS using pure asm. Unfortunately, I have lost all the traces of this wonderful piece of writing. Now I'm working with FreeDOS (precisely bootable FreeDOS flash card) and wondering how to proceed if someone decides to write his own memory allocator? What is the starting point and the logic of memory allocation without relying on OS mechanisms?


Solution

  • When DOS loads a .COM program, it allocates all of the memory available in the 640KB area (below 0a000h:00000h) to the program, and the program can manage its own memory. If it is desired to use MSDOS memory management, the program first has to release the memory using INT 21H, AH=49H, ES=segment, BX=# paragraphs. It can then use INT 21H, AH=48H, BX=# paragraphs, to allocate memory.

    As noted in the comments, an .EXE program may or may not allocate all of the memory in the 640KB area.

    Example .COM assembly code, to release, and then allocate all available memory. MSDOS will generally consume 16 bytes for its overhead. In this example, BX is set to the end of the code, then set to the next paragraph boundary that is 256 bytes past the end of the code to use as stack space. The end of this stack is the base of the memory released by the INT 21H, AH=4AH call.

            .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