; showregs.asm
;
; This short demonstration program illustrates concretely the
; folly of assuming that registers contain any particular values
; on startup of a DOS COM program.  The same lesson, it may be said,
; applies similarly to EXE files.  On startup, the only registers
; which have documented, guarenteed values are:
;
;   CS = DS = ES = SS = paragraph address of PSP
;   IP                = 100h
;   SP                = 0fffeh (a zero word has been pushed onto stack)
;
; Your debugger may explicitly set up other values, but don't be misled
; by it into thinking these are also the runtime values your program
; will always see.
;
; On my system, for example, the command line SHOWREGS X: Y: gives:
;
; AX = FFFF
; BX = FFFF
; CX = 00FF
; DX = 2229
; DI = FFFE
; SI = 0100
; BP = 091E
;
; written on Mon  04-03-1995  by Ed Beroset
;   and released to the public domain by the author
;
; to assemble and link, use Borland's Turbo Assembler:
;   TASM  showregs          ; assemble file
;   TLINK /Tdc showregs     ; link as DOS COM program
;
        .MODEL tiny
        .386
        .DATA

Message db      13,10,"AX = $"
MsgLen  = $-Message
        db      13,10,"BX = $"
        db      13,10,"CX = $"
        db      13,10,"DX = $"
        db      13,10,"DI = $"
        db      13,10,"SI = $"
        db      13,10,"BP = $"
        db      13,10,"CS = $"
        db      13,10,"DS = $"
        db      13,10,"ES = $"
        db      13,10,"SS = $"
MsgCount = ($-Message)/MsgLen
        db      13,10,'$'               ; final CRLF sequence

AL2ASCII MACRO
        and     al,0fh                  ; std macro turns low nybble
        add     al,90h                  ; of al into ASCII
        daa                             ; representation (0-9,A-F)
        adc     al,40h                  ; of corresponding hex digit.
        daa                             ; NOTE: destroys AL
ENDM

        .CODE
        org 100h
Start proc
        push    ss
        push    es
        push    ds
        push    cs
        push    bp                      ; save regs in reverse order
        push    si                      ;
        push    di                      ;
        push    dx                      ;
        push    cx                      ;
        push    bx                      ;
        push    ax                      ; we MUST push MsgCount regs!!
        mov     dx,offset Message       ; point to our messages
        mov     cx,MsgCount             ; number of regs to show
@@More:
        mov     ah,9                    ; DOS TTY mode print service
        int     21h                     ; go print our message
        pop     ax                      ; pop into AX for printing
        call    PrintAX                 ; and print it
        add     dx,MsgLen               ; advance to next message
        loop    @@More                  ; ... until we're done
        mov     ah,9                    ; print final CRLF sequence
        int     21h                     ; using same DOS call
        mov     ax,04c00h               ; DOS terminate with 0 errcode
        int     21h                     ; sayonara
Start endp

PrintAX PROC                            ;
        push    bx                      ; save used regs
        push    dx                      ;
        mov     bl,'$'                  ; stick DOS TTY terminator
        push    bx                      ; ... on the stack
        mov     bx,ax                   ; save old AX
        mov     ah,al                   ; calculate low nybbles first
        AL2ASCII                        ; standard macro
        xchg    al,ah                   ; recall high nybble
        shr     al,4                    ; put it into place
        AL2ASCII                        ; convert to ASCII
        push    ax                      ; save on stack
        mov     al,bh                   ; do high nybbles now
        mov     ah,al                   ; low half first
        AL2ASCII                        ; do it
        xchg    al,ah                   ; now recall high nybble
        shr     al,4                    ; put into place
        AL2ASCII                        ; calculate 'em
        push    ax                      ; save to stack
        mov     ah,9                    ; DOS TTY print function
        mov     dx,sp                   ; use stack as pointer
        int     21h                     ; call DOS function
        add     sp,6                    ; dispose of scrap on stack
        pop     dx                      ; recall used registers
        pop     bx                      ;
        ret                             ; return to caller
PrintAX ENDP
        END Start
