; TAIL.ASM
;
; Display the Command Tail from the Program Segment Prefix.
; Original concept by Alan Pinck.
;
; This is this algorithm:
;
;   static char newln[] = { "\r\n" };
;   main(){
;           char *si = (char *)0x81; /* memory location of tail */
;
;           while( *si != '\r' ){
;                   if( *si == ' ' ){
;                           printf("%s", newln);
;                           do {
;                                   ++si;
;                           } while( *si == ' ' );
;                           continue;
;                   }
;                   printf("%c",*si);
;                   ++si;
;           }
;           return 0;
;   }
;
; Note: The assembler needs to know whether an instruction operating on
; memory and a constant is operating on a single byte or a full 2-byte word.
; The syntax to specify a BYTE or a WORD looks like this:
;
;       cmp     BYTE PTR [si],0   ; compare one byte of memory with 0
;       cmp     WORD PTR [si],0   ; compare two bytes (a word) of memory
;
; Note: Many comments in this file are intended to teach students about the
; meaning of various assembler instructions.  They are NOT suitable
; for students documenting their own code, since they do not refer to
; any process or problem being solved.
;
; Students: Do NOT copy the teacher-style comments into your own code.
;
; -Ian! D. Allen - idallen@idallen.ca - www.idallen.com
;  November 1999, November 2009
;----------------------------------------------------------------------
; Both the Code Segment (CS) and Data Segment (DS) are the same.
Tail    segment
        assume  CS:Tail,DS:Tail
        org     100h            ; .COM requires this
;----------------------------------------------------------------------
start:
        ; char *si = (char *)0x81;
        ;
        mov     si,0081h        ; point to start of tail

whiler:
        ; while ( *si != '\r' )
        ;
        cmp     BYTE PTR [si],0Dh ; look for ending CR byte
        je      done            ; found it! exit loop

        ; if ( *si == ' ' )
        ;
        cmp     BYTE PTR [si]," " ; look for a blank
        jne     notsp           ; no blank - jump to notsp code

        ; printf("%s", newln);
        ;
        mov     dx,offset newln ; ASCII$ string containing CR+LF
        mov     ah,09h          ; code for "output ASCII$ string"
        int     21h

whiles:
        ; do { ++si; } while ( *si == ' ' );
        ;
        add     si,1h           ; increment tail pointer
        cmp     BYTE PTR [si]," " ; look for another blank
        je      whiles          ; keep looping if found

        ; continue;
        ;
        jmp     whiler          ; continue outer loop when no more blanks

notsp:
        ; printf("%c", *si);
        ;
        mov     dl,[si]         ; load byte from memory into DL
        mov     ah,02h          ; code for "output one ASCII char from DL"
        int     21h

        ; ++si;  (and jump back up to top of outer while loop)
        ;
        add     si,1h           ; increment pointer into tail
        jmp     whiler          ; go back for next character

done:
        ; return 0;
        ;
        mov     al,0h           ; return 0
        mov     ah,4Ch          ; code for "terminate program"
        int     21h
;----------------------------------------------------------------------
; Data and variables down here.
;
newln   db      0Dh,0Ah
        db      "$"             ; end of ASCII$ string
;----------------------------------------------------------------------
Tail    ends
        end start               ; "start" is the label on the first instruction

