 ; Tiny Pascal assembler code
          MOV   SP,OFFSET(STACKORG)
          MOV   BP,SP
          CALL  MAIN
          INT   020H
 ; <STDIO.HDR> included
;  STDIO.HDR
;
;  READ and WRITE routines needed for Tiny Pascal
;
SYS_RCHAR   PROC   NEAR   ; Read single character from stdin
            MOV    AH,1
            INT    021H
            RET           ; value comes back in AL
            ENDP

SYS_WRCHAR  PROC   NEAR   ; Write a single character (in DL) to stdin
            MOV    AH,2
            INT    021H
            RET
            ENDP

SYS_WHEX    PROC   NEAR   ; Write a single HEX number (in DL) to stdin
            CMP    DL,10
            JL     SYS_01
            ADD    DL,55     ; 'A' - 10
            CALL   SYS_WRCHAR
            RET
SYS_01      ADD    DL,'0'
            CALL   SYS_WRCHAR
            RET
            ENDP

SYS_IWRT    PROC   NEAR   ; Write an integer to stdout in HEX
            MOV    DH,4   ; used as a counter
SYS_11      ROL    AX
            ROL    AX
            ROL    AX
            ROL    AX
            MOV    DL,AL
            AND    DL,0FH
            PUSH   AX
            CALL   SYS_WHEX
            POP    AX
            DEC    DH
            JNZ    SYS_11
            RET
            ENDP

SYS_SWRT    PROC   NEAR   ; Write a string terminated by 0 to stdout
SYS_21      MOV    DL,0[BX]
            CMP    DL,0
            JNZ    SYS_22   ; zero terminator?
            RET
SYS_22      CALL   SYS_WRCHAR
            INC    BX
            JMPS   SYS_21
            ENDP

SYS_WRTLN   PROC   NEAR    ; write carriage return/line feed to stdout
            MOV    DL,0DH
            CALL   SYS_WRCHAR
            MOV    DL,0AH
            CALL   SYS_WRCHAR
            RET
            ENDP

READ        PROC   NEAR         ; read a HEX number from STDIN
            MOV    DX,0         ; clear DX
READ_01     CALL   SYS_RCHAR    ; get one character in AL
                    ; won't affect DX
            CMP    AL,0DH
            JNZ    READ_02
            PUSH   DX           ; save the thing we've done
            CALL   SYS_WRTLN    ; send a carriage return/line feed
            POP    AX           ; was an ENTER
            RET
READ_02     CMP    AL,' '
            JZ     READ_01      ; ignore spaces
            SUB    AL,'0'       ; start conversion to binary
            CMP    AL,9
            JLE    READ_03
            SUB    AL,7         ; turn 'A' into 0AH
READ_03     CMP    AL,0FH
            JLE    READ_04
            SUB    AL,32        ; turn 'a' into 0AH
READ_04     AND    AL,0FH       ; clip for good measure
            SHL    DX           ; prepare DX for hex value
            SHL    DX
            SHL    DX
            SHL    DX
            OR     DL,AL
            JMPS   READ_01      ; go do some more
            ENDP

READLN      PROC   NEAR
            JMPS   READ         ; does the same thing
            ENDP

 ; ... end of include STDIO.HDR
 ;   {TURUN -- A sample program written in Tiny Pascal }
 ;   var I, J, K, PROBLEM;
 ;   
 ;   {*********************}
 ;   function ISLESS(N1, N2);
 ;   begin  {returns 1 if n1<n2, 0 otherwise}
 ;     if n2-n1 then isless:=1   {truth value test is >0}
 ;     else isless:=0;
 ;     end;
ISLESS    PROC  NEAR
          PUSH  BP
          MOV   BP,SP
          MOV   AX,4[BP] ; N2
          SUB   AX,6[BP] ; N1
          CMP   AX,0
          JLE   XXX0
          MOVW  8[BP],1 ; ISLESS
          JMP   XXX1
XXX0      EQU   $
          MOVW  8[BP],0 ; ISLESS
XXX1      EQU   $
          MOV   AX,8[BP] ; ISLESS
          POP   BP
          RET   6
          ENDP
 ;    SYMBOL TABLE
 ; ISLESS                          8[BP]
 ; N1                              6[BP]
 ; N2                              4[BP]

 ;     
 ;   function ADDEMUP(LOWER, UPPER, SUM);
 ;   begin end;    {makes it a forward declaration}
 ;   
 ;   {*********************}
 ;   function ISEQUAL(N1, N2);
 ;   begin
 ;     if n2-n1 then isequal:=0   {false}
 ;     else
 ;     if n1-n2 then isequal:=0
 ;     else isequal:=1;
 ;     end;
ISEQUAL   PROC  NEAR
          PUSH  BP
          MOV   BP,SP
          MOV   AX,4[BP] ; N2
          SUB   AX,6[BP] ; N1
          CMP   AX,0
          JLE   XXX2
          MOVW  8[BP],0 ; ISEQUAL
          JMP   XXX3
XXX2      EQU   $
          MOV   AX,6[BP] ; N1
          SUB   AX,4[BP] ; N2
          CMP   AX,0
          JLE   XXX4
          MOVW  8[BP],0 ; ISEQUAL
          JMP   XXX5
XXX4      EQU   $
          MOVW  8[BP],1 ; ISEQUAL
XXX5      EQU   $
XXX3      EQU   $
          MOV   AX,8[BP] ; ISEQUAL
          POP   BP
          RET   6
          ENDP
 ;    SYMBOL TABLE
 ; ISEQUAL                         8[BP]
 ; N1                              6[BP]
 ; N2                              4[BP]

 ;     
 ;   {***********************}
 ;   function ADDEMUP(LOWER, UPPER, SUM);
 ;         {SUM is a local}
 ;   begin
 ;     sum:=0;
 ;     while isless(lower, upper) do begin
 ;       sum:=sum+lower;
 ;       lower:=lower+1;
 ;       end;
 ;     addemup:=sum+lower;  { the last one was left out }
 ;     end;
ADDEMUP   PROC  NEAR
          PUSH  BP
          MOV   BP,SP
          MOVW  4[BP],0 ; SUM
XXX6      EQU   $
          PUSH  AX
          MOV   AX,8[BP] ; LOWER
          PUSH  AX
          MOV   AX,6[BP] ; UPPER
          PUSH  AX
          CALL  ISLESS
          CMP   AX,0
          JLE   XXX7
          MOV   AX,4[BP] ; SUM
          ADD   AX,8[BP] ; LOWER
          MOV   4[BP],AX ; SUM
          MOV   AX,8[BP] ; LOWER
          ADD   AX,1
          MOV   8[BP],AX ; LOWER
          JMP   XXX6
XXX7      EQU   $
          MOV   AX,4[BP] ; SUM
          ADD   AX,8[BP] ; LOWER
          MOV   10[BP],AX ; ADDEMUP
          MOV   AX,10[BP] ; ADDEMUP
          POP   BP
          RET   8
          ENDP
 ;    SYMBOL TABLE
 ; ADDEMUP                         10[BP]
 ; LOWER                           8[BP]
 ; UPPER                           6[BP]
 ; SUM                             4[BP]

 ; 
 ;   {*********************}
 ;   function MAIN(SUM, UPPER);
 ;   begin
 ;     i:=1;
 ;     j:=i+5;
 ;     k:=j-16;
 ;     problem:=i+(j*k);
 ;     writeln('I: ', i, ' J: ', j, ' K: ', k, ' Problem: ', problem);
 ;     write('Enter upper ');
 ;     upper:=read;
 ;     sum:=addemup(1, upper);  {sum of integers 1..upper}
 ;     if isequal(sum, (upper*(upper+1))/2) then
 ;       writeln('Sum = ', sum)
 ;     else begin
 ;       writeln('BUG: Sum = ', sum, '; should be ',
 ;                  (upper*(upper+1))/2);
 ;       end;
 ;     end;
MAIN      PROC  NEAR
          PUSH  BP
          MOV   BP,SP
          MOVW  I,1 ; I
          MOV   AX,I ; I
          ADD   AX,5
          MOV   J,AX ; J
          MOV   AX,J ; J
          SUB   AX,16
          MOV   K,AX ; K
          MOV   AX,K ; K
          PUSH  AX
          MOV   AX,J ; J
          POP   CX
          IMULW CX
          PUSH  AX
          MOV   AX,I ; I
          POP   DX
          ADD   AX,DX
          MOV   PROBLEM,AX ; PROBLEM
          MOV   BX,OFFSET(SS0)
          CALL  SYS_SWRT
          MOV   AX,I ; I
          CALL  SYS_IWRT
          MOV   BX,OFFSET(SS1)
          CALL  SYS_SWRT
          MOV   AX,J ; J
          CALL  SYS_IWRT
          MOV   BX,OFFSET(SS2)
          CALL  SYS_SWRT
          MOV   AX,K ; K
          CALL  SYS_IWRT
          MOV   BX,OFFSET(SS3)
          CALL  SYS_SWRT
          MOV   AX,PROBLEM ; PROBLEM
          CALL  SYS_IWRT
          CALL  SYS_WRTLN
          MOV   BX,OFFSET(SS4)
          CALL  SYS_SWRT
          CALL  READ
          MOV   4[BP],AX ; UPPER
          PUSH  AX
          MOV   AX,1
          PUSH  AX
          MOV   AX,4[BP] ; UPPER
          PUSH  AX
          MOV   AX,0
          PUSH  AX
          CALL  ADDEMUP
          MOV   6[BP],AX ; SUM
          PUSH  AX
          MOV   AX,6[BP] ; SUM
          PUSH  AX
          MOV   AX,2
          PUSH  AX
          MOV   AX,4[BP] ; UPPER
          ADD   AX,1
          PUSH  AX
          MOV   AX,4[BP] ; UPPER
          POP   CX
          IMULW CX
          CWD
          POP   CX
          IDIVW CX
          PUSH  AX
          CALL  ISEQUAL
          CMP   AX,0
          JLE   XXX8
          MOV   BX,OFFSET(SS5)
          CALL  SYS_SWRT
          MOV   AX,6[BP] ; SUM
          CALL  SYS_IWRT
          CALL  SYS_WRTLN
          JMP   XXX9
XXX8      EQU   $
          MOV   BX,OFFSET(SS6)
          CALL  SYS_SWRT
          MOV   AX,6[BP] ; SUM
          CALL  SYS_IWRT
          MOV   BX,OFFSET(SS7)
          CALL  SYS_SWRT
          MOV   AX,2
          PUSH  AX
          MOV   AX,4[BP] ; UPPER
          ADD   AX,1
          PUSH  AX
          MOV   AX,4[BP] ; UPPER
          POP   CX
          IMULW CX
          CWD
          POP   CX
          IDIVW CX
          CALL  SYS_IWRT
          CALL  SYS_WRTLN
XXX9      EQU   $
          MOV   AX,8[BP] ; MAIN
          POP   BP
          RET   6
SS7       DB    '; should be ',0
SS6       DB    'BUG: Sum = ',0
SS5       DB    'Sum = ',0
SS4       DB    'Enter upper ',0
SS3       DB    ' Problem: ',0
SS2       DB    ' K: ',0
SS1       DB    ' J: ',0
SS0       DB    'I: ',0
          ENDP
 ;    SYMBOL TABLE
 ; MAIN                            8[BP]
 ; SUM                             6[BP]
 ; UPPER                           4[BP]

 ; 
 ; GLOBAL VARIABLES
PROBLEM   DW    0
I         DW    0
J         DW    0
K         DW    0
 ; RUNTIME STACK
          DS    2000
STACKORG  DW    0
 ; MAIN stack space
          DW    0
          DW    0
          DW    0
; NO errors
