COMMENT ~
 PROGRAM: EMEM.ASM (based on EMEM.C)
  AUTHOR: Denis Boyles
 RELEASE: Public Domain (Dec  1, 1996)

 COMPILE: Arrowsoft Assembler (MASM v3.0)
      OS: MS-DOS (v6.20)

 PURPOSE: an assembly version of my C program that display environment
          memory usage.
~

;--------------------------------------
;define our default segments
;--------------------------------------

CODE SEGMENT
    ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
    ORG 0100h

;--------------------------------------
;program starts here
;--------------------------------------

MAIN:
    call    esize                      ;get total allocated space of env
    push    AX                         ;save total value to stack
    mov     DI,offset total+4          ;set ones index into our buffer to
    call    DecToAsc                   ;`print' the value to our buffer

    call    eused                      ;get used environment space
    push    AX                         ;save used value to stack
    mov     DI,offset used+4           ;set ones index into our buffer to
    call    DecToAsc                   ;`print' the value to our buffer

    pop     BX                         ;load BX with saved used value
    pop     AX                         ;load AX with total value
    sub     AX,BX                      ;subtract to get free space left in AX
    mov     DI,offset free+4           ;set ones index into our buffer to
    call    DecToAsc                   ;`print' the value to our buffer

    mov     AH,009h                    ;DOS print an ASCIID string
    mov     DX,offset report           ;DS:DX -> the string to print
    int     021h                       ;call DOS to print our report

    mov     AX,04C00h                  ;DOS terminate program with code (0)
    int     021h                       ;call DOS to end program


;--------------------------------------
;data goes here
;--------------------------------------

report      db 00Dh,00Ah,"Total Environment Space: "
total       db "      bytes.",00Dh,00Ah
            db " Used Environment Space: "
used        db "      bytes.",00Dh,00Ah
            db "------------------------ ----- ------",00Dh,00Ah
            db " Free Environment Space: "
free        db "      bytes.",00Dh,00Ah,'$'

;--------------------------------------
;DecToAsc - makes ASCII number
;   AX <= unsigned 16bit num to print
;   DI <= buffer start of ones place
;--------------------------------------

DecToAsc proc
    std                                ;set direction flag to count down
    mov     CX,00Ah                    ;set our divisor constant 10

DTA0:
    cmp     AX,009h                    ;can we still divide by 10?
    jb      DTA1                       ;YES if number is > 10 so do it again

    xor     DX,DX                      ;zero out DX so we divide by 10
    div     CX                         ;divide number AX by 10
    mov     BX,AX                      ;save quotient AX to BX
    mov     AL,DL                      ;copy remainder to AL for storing
    add     AL,'0'                     ;convert number to ASCII by adding '0'
    stosb                              ;store ASCII into our buffer ES:DI
    mov     AX,BX                      ;restore new quotient to AX
    jmp     DTA0
DTA1:
    add     AL,'0'                     ;NO our last number, convert to ASCII
    stosb                              ;and store it into our buffer
    ret                                ;back to caller
DecToAsc endp

;--------------------------------------
;esize - report total environment size
;   AX => total size in bytes of env
;--------------------------------------

esize proc
    push    ES                         ;save ES register to stack

    mov     AX,03522h                  ;DOS get vector for INT 22h where
    int     021h                       ;ES:BX -> COMMAND.COM?

    mov     AX,ES:[02Ch]               ;get environment segment from CC's PSP
    dec     AX                         ;minus one for the env's MCB
    mov     ES,AX
    mov     AX,ES:[003h]               ;get the size of MCB word
    mov     CL,004h                    ;shift left 4 bits to convert paras
    shl     AX,CL                      ;into bytes
    pop     ES                         ;restore ES from stack
    ret                                ;back to caller
esize endp

;--------------------------------------
;eused - walk env and count used bytes
;   AX => used bytes of environment
;--------------------------------------

eused proc
    push    DS                         ;save DS to stack

    mov     AX,DS:[02Ch]               ;get the environment segment from our
    mov     DS,AX                      ;PSP and set DS to it for SI?
    xor     SI,SI                      ;zero out our SI counter
    cld                                ;clear direction flag to count up

CntEnv:
    cmp     word ptr [SI],00000h       ;are we at the end of environment?
    jz      EndEnv                     ;YES then stop counting
    inc     SI                         ;NO then increment our counter
    jmp     CntEnv                     ;and keep on counting until end
EndEnv:
    add     SI,002h                    ;include the two NULL end markers
    mov     AX,SI                      ;copy to AX for return value
    pop     DS                         ;restore DS register
    ret                                ;back to caller
eused endp

CODE ENDS
END MAIN
