title global storage functions include asm.inc public global_alloc public global_calloc public global_free public global_lock public global_realloc public global_unlock GLOBAL_MAX equ 100 ; maximum number of storage handles NULL_HANDLE equ 0 global_str struc g_address dd ? ; storage address g_lock dw ? ; storage lock count g_size dw ? ; size of storage global_str ends .data? global_count dw ? ; number of allocated handles global_table global_str GLOBAL_MAX dup(<>) .code extn calloc,clear_strerror,free,malloc,realloc ;; global alloc ; ; entry CX requested size ; exit AX actual size ; BX storage handle (never zero) ; Cf if no storage ; global_alloc proc pushm di,es call malloc jc gal1 ; if not enough memory call global_alloc_common gal1: popm es,di ret global_alloc endp ;; global alloc common ; ; entry AX storage size ; ES:DI storage pointer ; exit BX storage handle ; Cf if out of handles ; global_alloc_common proc pushm ax,dx,cx,si,ds mov dx,ax mov bx,GLOBAL_MAX mov cx,bx cmp cx,global_count[bp] jbe gac2 ; if out of handles mov si,@data mov ds,si lea si,global_table-size global_str gac1: add si,size global_str ; search for first free handle (SLOW!) mov ax,wptr g_address[si] or ax,wptr g_address[si+2] loopnz gac1 jnz gac2 ; if unexpected error: corrupted data mov g_lock[si],ax mov g_size[si],dx mov wptr g_address[si],di mov wptr g_address[si+2],es inc global_count[bp] sub bx,cx ; compute non-zero handle 1..n (Cf=0) gac2: popm ds,si,dx,cx,ax ret gac3: stc jmp gac2 global_alloc_common endp ;; global calloc ; ; entry CX requested size ; exit AX actual size ; BX storage handle (never zero) ; Cf if no storage ; global_calloc proc pushm di,es call calloc jc gca1 ; if not enough memory call global_alloc_common gca1: popm es,di ret global_calloc endp ;; global free ; ; entry BX storage handle (OK if zero) ; exit BX 0 ; uses AX ; global_free proc pushm di,es cmpx bx,NULL_HANDLE je gfr1 ; if NULL handle, just return call read_global_entry mov bx,NULL_HANDLE jc gfr1 ; if bad handle les di,g_address[si] call free mov wptr g_address[si],di mov wptr g_address[si+2],es gfr1: popm es,di ret global_free endp ;; global lock ; ; entry BX valid storage handle ; exit DS:SI storage pointer ; note DOES NOT BASH AX ; global_lock proc call read_global_entry jc glk1 ; if bad handle inc g_lock[si] lds si,g_address[si] glk1: ret global_lock endp ;; global realloc ; ; entry BX storage handle ; CX new size ; exit AX actual size (if no errors) ; Cf if not enough memory ; global_realloc proc pushm di,si,ds,es call read_global_entry jc gre1 ; if bad handle les di,g_address[si] call realloc jnc gre1 ; if realloc OK mov ax,g_lock[si] ; check lock count before moving add ax,-1 jc gre1 ; if locked, cannot move call clear_strerror ; else clear realloc error call malloc jc gre1 ; if no memory pushm ax,di,es ; copy old storage to new storage pushm cx,si,ds mov cx,g_size[si] lds si,g_address[si] rep movsb popm ds,si,cx les di,g_address[si] ; free old storage call free popm es,di,ax mov wptr g_address[si],di ; set new storage pointer and size mov wptr g_address[si+2],es mov g_size[si],ax clc gre1: popm es,ds,si,di ret global_realloc endp ;; global unlock ; ; entry BX valid storage handle ; note flags do NOT change ; global_unlock proc pushf pushm si,ds call read_global_entry jc gun1 ; if bad handle dec g_lock[si] gun1: popm ds,si popf ret global_unlock endp ;; read global entry ; ; entry BX global handle ; exit DS:SI global table for handle ; Cf if bad handle ; read_global_entry proc pushm ax,dx mov ax,@data mov ds,ax lea si,global_table cmp bx,GLOBAL_MAX ja rge1 ; if bad handle mov ax,bx ; multiply handle by structure size dec ax ; to select global table entry mov dx,size global_str mul dx add si,ax rge1: popm dx,ax ret read_global_entry endp end