;RAMFREE
;determine amount of available RAM without using CHKDSK
;Kim Kokkonen, TurboPower Software, 6/85
;written for MASM or TASM
;Updated 10/20/91
;   work for free memory greater than 640K
;   add size of environment block
;
Cseg    segment public para
        assume  cs:Cseg, ds:Cseg, es:Cseg

        org     100H
ramfree proc    near

;shrink memory available to this program
coment: mov     bx,offset theend
        add     bx,15
        mov     cl,4
        shr     bx,cl                   ;convert bytes to paragraphs
        mov     ah,4AH
        int     21H                     ;DOS SETBLOCK function

;try to allocate the maximum memory
        mov     ah,4AH
        mov     bx,0FFFFH
        int     21H                     ;use SETBLOCK again
                                        ;BX contains paragraphs available

;add size of environment
        mov     ax,ds:[002CH]
        dec     ax
        mov     es,ax
        add     bx,es:[0003H]

;convert paragraphs to a doubleword number of bytes in dx:ax
        mov     ax,bx
        xor     dx,dx
        mov     dl,ah                   ;dl will contain top four bytes of ah
        mov     cl,4
        shr     dx,cl
        shl     ax,cl

;convert doubleword dx:ax to an ASCII string
        mov     di,offset outp$         ;di indexes next output position
        mov     si,offset digits        ;si indexes digit table

nextd:  mov     cx,[si]                 ;low word of digit
        add     si,2
        mov     bx,[si]                 ;high word of digit
        add     si,2
        xor     bp,bp                   ;counter for this digit
nextc:  sub     ax,cx
        sbb     dx,bx
        jc      ddone                   ;jump if carry
        inc     bp                      ;else increment counter
        jmp     nextc
ddone:  add     ax,cx                   ;undo last subtraction
        adc     dx,bx
        mov     cx,bp                   ;counter into cx
        cmp     di,offset outp$         ;first output character?
        jne     store                   ;output zeros if not leading
        jcxz    chknc                   ;no output for leading zeros
store:  or      cl,30H                  ;convert count to digit
        mov     [di],cl                 ;store output
        inc     di                      ;next output position
chknc:  cmp     si,offset theend        ;all of table?
        jb      nextd                   ;loop if not

;now output the string and halt
        mov     dx,offset bmess$
        mov     ah,09H
        int     21H                     ;print string
        mov     ax,4C00H
        int     21H

ramfree endp

;data area
bmess$  db      'RAM bytes available: '
outp$   db      32,32,32,32,32,32,32,13,10,36           ;ASCII output string
digits  dd      1000000,100000,10000,1000,100,10,1      ;conversion table
theend  label   byte

Cseg    ends
        end     ComEnt
