Skip to content
FreeDOSDeep Dive Published Updated 6 min readViews unavailable

FreeDOS INT 21h AH=58h: Allocation Strategy and UMB Routing

Query and set DOS INT 21h/AH=58h allocation strategies, route allocations through UMBs, and restore global state using FreeDOS source evidence.

INT 21h/AH=58h controls how later DOS memory-allocation requests search the conventional/upper-memory arena. It does not allocate memory by itself: AH=48h remains the request operation, and AH=49h and AH=4Ah release or resize blocks. This separation is easy to miss because the strategy call changes the allocator’s future policy without returning a segment or a block size.

The function is especially relevant when an application or installer wants a resident component to use an Upper Memory Block (UMB) instead of consuming conventional memory. UMBs are not automatically available just because the CPU supports extended memory. A compatible memory manager and DOS configuration must expose the region, and the UMB chain must be linked into DOS’s allocation chain before UMB-directed strategies can use it. The behavior below is pinned to the FreeDOS kernel source revision cited at the end; DOS clones and older releases can differ.

Register contract

The main function is selected by AH=58h; AL selects the subfunction:

Call Inputs Result or effect
AL=00h AH=58h Query current strategy; FreeDOS returns it in AL.
AL=01h BL = strategy value Set strategy for subsequent DOS allocations.
AL=02h AH=58h Query UMB link state; FreeDOS returns the state in AL.
AL=03h BX=0000h unlink or BX=0001h link Change whether the UMB chain participates in the DOS arena, if a UMB region is available.

The FreeDOS function-support table is an older compatibility record identified as build 2036 (2006): it records 5800h and 5801h as DOS 3.0-era services, and 5802h/5803h as DOS 5.0-era services. Treat that table as historical evidence, not a current guarantee for every DOS-compatible kernel. A program targeting several implementations should check carry and preserve AX immediately on failure; do not infer support solely from a displayed DOS version string, because compatibility layers can report a different version from the implementation behind the call.

The values accepted for AL=01h in the pinned FreeDOS implementation are:

BL FreeDOS strategy
00h, 01h, 02h First-fit, best-fit, or last-fit in the currently linked arena.
40h, 41h, 42h Corresponding strategy restricted to UMBs when the UMB chain is linked.
80h, 81h, 82h Try UMBs first, then fall back to conventional memory if no suitable UMB is found.

Those encodings come from FreeDOS’s mcb.h constants and the AH=58h dispatcher. They are not instructions to search XMS or EMS handles; those are different memory interfaces with different ownership rules.

What first-fit, best-fit, and last-fit mean here

In the pinned allocator, first-fit selects the first free MCB large enough for the request in the chain’s current search order. Best-fit scans for the smallest qualifying free MCB, retaining the earlier candidate when two blocks have the same size. Last-fit keeps the last qualifying candidate; when it splits a block, it allocates the requested region from the end of that block. These are source-specific implementation details, not a promise that every DOS kernel orders its chain or resolves ties identically.

For UMB-first modes (80h through 82h), FreeDOS begins at the UMB root when upper memory is linked. If no suitable UMB is found, the allocator clears the UMB-first flag and retries with the corresponding conventional strategy. UMB-only modes (40h through 42h) do not request that fallback. But the mode does not link UMBs for you: query the state with AL=02h and verify that the machine actually has usable blocks before depending on the result.

There is a subtle safety boundary in this source revision. When its global UMB-link state is false, the allocator starts at the ordinary first MCB instead of searching from the UMB root. That affects both the 40h–42h UMB-only encodings and the 80h–82h UMB-first encodings: none of those values links the UMB chain, and this revision does not search upper memory while it remains unlinked. Therefore, do not treat either mode family as a reliable placement guarantee until the link state and usable blocks have been verified on the target kernel. This is an implementation finding for the cited revision, not a claim that every DOS-compatible kernel behaves the same way.

Save and restore the policy around a request

The strategy stored in FreeDOS’s mem_access_mode and the UMB-link flag are kernel variables, not a private allocation policy attached to one PSP. Changing them affects later allocator calls in the same DOS environment. Do not set a preferred mode at program startup and leave it behind for the next program, shell command, or resident component. Query the current value, change only what the current operation needs, and restore the saved value on success and every error path.

A minimal assembly sequence to query the strategy and confirm that UMBs are linked is:

        mov     ax, 5800h        ; query allocation strategy
        int     21h
        jc      no_strategy_api
        mov     [old_strategy], al

        mov     ax, 5802h        ; query UMB-link state
        int     21h
        jc      no_umb_query
        test    al, 01h
        jz      use_conventional_policy

Only after confirming that the UMB chain is linked should a program consider setting BL=80h for first-fit UMB-first behavior or a 40h mode for UMB-only behavior. Call AH=48h for the actual allocation, then restore the byte saved by 5800h through AX=5801h. Check the carry flag on both the set and restore calls. If the restoration fails, report that separately; do not silently claim the process left the allocator as it found it. Keep the error path structured so every successful policy change reaches the same restoration code.

Avoid changing UMB linkage unless the program truly owns that system-wide policy decision. AL=03h with BX=0 unlinks and BX=1 links the chain in the cited implementation; if no UMB root exists, FreeDOS reports an invalid-function error. If a program does deliberately change linkage, it must query and save the prior state with 5802h, verify the transition, and restore that state as carefully as the allocation strategy. Linking a chain can make additional MCBs visible; unlinking it can make existing upper blocks unavailable to future DOS allocations. Neither operation is a harmless display preference.

Verify the real target, not just the register result

Use a disposable FreeDOS VM or a restorable disk image. Record the actual kernel build, memory-manager configuration, initial 5800h result, and 5802h link state. Test small allocations under ordinary first-fit and UMB-first modes, inspect the returned segment and MCB layout with trusted diagnostics, and restore the original policy before leaving the test program. Include the no-UMB configuration and an unlinked-UMB configuration so a test can catch accidental low-memory placement when the code expected an upper block.

MEM output is useful for aggregate conventional and upper-memory capacity, but it does not prove that one particular AH=48h call used the intended address range. Verify the returned segment and block ownership as well. Do not edit MCBs directly, infer a stable segment from one boot, or change CONFIG.SYS on a working machine just to force a preferred fit strategy.

The safe mental model is simple: AH=58 changes allocator search policy; AH=48 still owns the allocation; UMB strategies depend on UMB availability and link state; and the policy is shared kernel state that must be restored. Treat each of those as an observable precondition rather than assuming a strategy byte guarantees a particular physical address.

Related:

Sources:

Comments