home *** CD-ROM | disk | FTP | other *** search
- ; ISETUP.A - Setup for C program execution on IBM PC.
-
- ; jumped to by first instruction to do C initilization.
- ; DS:0 is program segment prefix.
- ; SS is program DS.
- ; SS:0 is size of C initilized memory.
- ; SS:2 is size of uninitilized memory.
-
- ; EQUs define fields.
-
- IBM EQU 21H ;IBM DOS INTERRUPT NUMBER
- CI_CODE EQU 1
- CO_CODE EQU 2
- DIRECT_CODE EQU 6
- DIRECT_INPUT EQU 7
- VERSION EQU 30H
- READ EQU 3FH
- SETBLK EQU 4AH
- TERMINATE EQU 4CH
-
- BS EQU 8
- TAB EQU 9
- LF EQU 0AH
- CR EQU 0DH
- CONTS EQU 19
- CONTX EQU 24
-
- DSEG
- PUBLIC _PCB_,_MSDOS2_ ;USED BY CHAIN
- NE_MSG DB 'not enough memory',10
- MEMFROM DW 0 ;FIRSE FREE BYTE IN DS
- _PCB_ DW 0 ;_PCB_ SEGMENT REGISTER
- _ORIGSP_ DW 0 ;STARTING SP. CAUTION: MUST FOLLOW
- ;_PCB_
- _MSDOS2_ DB 0 ;1 IF VERSION 2.0 OR ABOVE
- LASTCH DB 0
- CURCH DB 0
- PUBLIC ERRNO_
- ERRNO_ RW 1 ;ERROR NUMBER
-
- CSEG
-
- PUBLIC _CSETUP,EXIT_,PUTCHAR_,GETCHAR_,PUTS_,MAIN_
-
- ; this is the actual entry point for a C88 program.
- ; the following initilization must take place before a program
- ; is actually called.
-
- ; 1) set SP to highest available byte.
- ; 2) set uninitilized storage to zero.
- ; 3) calculate argc and argv.
- ; 4) set DS to users data area.
- ; 5) call main(argc,argv).
-
- ; if program returns then goto exit.
-
-
- ; SET SP.
-
- _CSETUP:
- MOV SS:_PCB_,DS ;SAVE _PCB_ FOR EXIT CALL
- MOV AX,[2] ;IBM PUTS TOTAL SYSTEM PARAGRAPHS HERE
- MOV BX,SS ;CURRENT SS:SP MUST BE WITHIN AVAILABLE
- SUB AX,BX ;PARAGRAPHS AVAILABLE FOR DATA
- JBE NOT_ENOUGH
- DEC AX ;PLAY IT SAFE
- CMP AX,1000H ;IF OVER 64K THEN SET SP TO 64K
- JC UNDER_64
- MOV AX,0FFFH ;MAXIMUM STACK WITHOUT WRAP
- UNDER_64:
- MOV CL,4 ;TURN PARAGRAPH INTO BYTE
- SHL AX,CL
- CMP AX,SP ;SEE IF BIG ENOUGH
- JC NOT_ENOUGH
- MOV BX,SS:[0] ;IF SP IS INIT DATA+RESDATA+127 THEN MAKE MAX.
- ADD BX,SS:[2]
- ADD BX,127
- CMP SP,BX ;WANT MAXIMUM ?
- JNZ HAVE_SP ;NO, MUST HAVE HAS A -Snn OPTION OF BIND
- MOV SP,AX ;HAVE A GOOD STACK
- HAVE_SP:MOV SS:_ORIGSP_,SP ;REMEMBER STACK FOR EXEC
-
-
- ; REMEMBER VERSION NUMBER
-
- MOV AH,VERSION ;CODE TO ASK FOR VERSION
- INT IBM
- CMP AL,2 ;IS IT 2 OR ABOVE ?
- JB OLDVER
- MOV SS:_MSDOS2_,1 ;TRUE IF VERSION 2 OR ABOVE
- OLDVER:
-
- ; CALCULATE ARGC AND ARGV. THE COMMAND TAIL IS BETWEEN 129 AND
- ; 255. COMMNAD TAIL IN COPIED TO TOP OF STACK AND ARGV VECTOR
- ; IS PLACED UNDER IT. THE COMMAND NAME IS LAMENTABLY NULL.
-
- MOV BYTE [255],CR ;DONT FALL OFF END IF INVALID
- MOV BYTE [128],' ' ;DONT FALL OFF START EITHER (REPLACES LENGTH)
- MOV CX,1 ;NUMBER OF ARGUMENTS. ALWAYS (NULL) COMMAND
- MOV SI,-1 ;LENGTH OF ARGUMENTS.
- ; FIND SIZE OF TAIL
- CMD_COUNT:
- INC SI
- MOV AL,[SI+129] ;NEXT COMMAND CHAR
- CMP AL,CR ;CR OR LF IS END OF LINE
- JZ END_COUNT
- CMP AL,LF
- JNZ CMD_COUNT
- END_COUNT:
- MOV AX,0 ;NEED ZERO AT END
- PUSH AX
- TEST SI,1 ;NEED WORD ALLIGNED STACK
- JZ WORD_A
- INC SP ;ODD NOW SO EVEN LATER
- WORD_A: MOV DI,SP ;REMEMBER LOC OF ZERO
- SUB SP,SI ;MAKE ROOM FOR TAIL
- MOV BP,SP ;BP CAN ADDRESS NEW TAIL
- NTAIL: DEC SI
- CMP SI,-1 ;-1 WHEN DONE
- JZ SAVE_ARGS
- ; A NON WHITE SPACE PRECEEDED BY WHITE MEANS ANOTHER ARGUMENT
- MOV AL,[SI+129]
- CMP AL,' ' ;SEE IF WHITE
- JZ WHITE
- CMP AL,TAB
- JNZ NOT_WHITE
- WHITE: MOV AL,0 ;SET WHITE TO NULL FOR END OF STRING
- JMP STUFF
-
- ; IS PRECEEDING A WHITE?
- NOT_WHITE:
- CMP BYTE [SI+128],' '
- JZ NEW_ARG
- CMP BYTE [SI+128],TAB
- JNZ STUFF
- NEW_ARG:LEA BX,[BP+SI] ;STORE ARGV ELEMENT
- PUSH BX
- INC CX ;INCREMENT ARGC
- STUFF: MOV [BP+SI],AL ;PUT TAIL CHAR ON STACK
- JMP NTAIL
-
- ; SAVE A POINTER TO A ZERO FOR ARGV[0]
- SAVE_ARGS:
- PUSH DI
-
- ; SAVE ARGV AND ARGC
- MOV BP,SP ;DONT PUSH SP AS 286 IS DIFFERENT
- PUSH BP ;*ARGV[]
- PUSH CX ;ARGC
-
- ; SET DS TO CORRECT VALUE
-
- MOV AX,SS
- MOV DS,AX
-
- ; INITILIZE UNINITILIZED MEMORY TO ZERO
-
- MOV DI,[0] ;LENGTH OF INITILIZED MEMORY IS HERE
- MOV CX,[2] ;LENGTH OF UNINITILIZED IS HERE
- MOV ES,AX ;ES=DS
- MOV AL,0 ;THE ZERO
- CLD
- REP STOSB
-
- ; REMEMBER LOW ADDRESS OF FREE MEMORY
-
- ADD DI,2 ;MAKE WORD ALLIGNED
- AND DI,0FFFEH
- MOV MEMFROM,DI ;PUT AWAY FOR MEMORY CALL
-
- ; NOW READY FOR MAIN
-
- CALL MAIN_ ;AND DO THE PROGRAM
-
- ; FALL INTO EXIT IF RETURN
-
- MOV AL,0 ;SET RETURN CODE TO ZERO
- JMP DOEXIT
-
- ; exit();
-
- EXIT_: POP AX ;RETRIEVE RETURN CODE
- POP AX
- DOEXIT: ;IN DOS 2.0 USE CODE 4C TO TERMINATE
- ;AS THIS ALLOWS AN ERROR CODE
- CMP _MSDOS2_,0 ;DOS 1.0 ?
- JZ OLDEND
- MOV AH,TERMINATE ;DOC 2.0 TERMINATE CODE
- INT IBM
-
-
- OLDEND: PUSH _PCB_ ;CREATE A LONG RETURN TO _PCB_:0
- MOV AX,0
- PUSH AX
- LRET
-
- NOT_ENOUGH:
- MOV AX,&NE_MSG
- PUSH AX
- CALL PUTS_
- ADD SP,2
- MOV AL,2 ;ERROR EXIT
- JMP DOEXIT
-
-
- ; charactor = getchar();
-
- GETCHAR_:
- CMP LASTCH,0 ;SAVED CHAR
- JZ DOGC
- GLAST: MOV AL,LASTCH ;RETURN LAST CHAR
- MOV LASTCH,0
- JMP GOTIN
- DOGC: MOV AH,CI_CODE ;CODE FOR ECHOED INPUT
- INT IBM ;DO THE CONSOLE READ
- GOTIN: MOV AH,0 ;RETURN A WORD
- CMP AL,26 ;CONTROL z ?
- JZ READNFG
- RET ;CHARACTER IS IN AL
- READNFG:MOV AX,-1 ;-1 IF EOF
- RET
-
-
- ; putchar(character);
-
- PUTCHAR_:POP AX ;RETURN ADDRESS
- POP DX ;DL IS CHARACTER
- PUSH DX
- PUSH AX
- CMP DL,LF ;MUST CHANGE LF TO CR,LF
- JNZ XCO
- MOV DL,CR ;PRINT THE CR FIRST
- CALL XCO
- MOV DL,LF ;PUT THE LF BACK
- XCO: MOV AH,CO_CODE
- INT IBM ;DO THE WRITE
- RET
-
-
- ; puts(string address);
-
- PUTS_: POP AX ;RETURN ADDRESS
- POP BX ;STRING ADDRESS
- PUSH BX
- PUSH AX
- PS_LP: MOV AL,[BX] ;NEXT CHAR
- OR AL,AL
- JZ PS_END ;ZERO AT END OF STRING
- PUSH BX
- PUSH AX ;CHAR
- CALL PUTCHAR_ ;LET PUTCHAR TURN LF INTO CR,LF
- ADD SP,2
- POP BX
- INC BX ;STRING POINTER
- JMP PS_LP
- PS_END: RET
-
-
-
-
- PUBLIC CI_, CO_, CSTS_
-
- ; charactor = ci();
-
- CI_: CMP LASTCH,0 ;SAVED CHAR
- JZ DOCI
- MOV AL,LASTCH ;RETURN LAST CHAR
- MOV LASTCH,0
- MOV AH,0
- RET
- DOCI: MOV AH,DIRECT_INPUT ;CODE FOR DIRECT CONSOLE INPUT
- INT IBM
- MOV AH,0 ;MAKE AN INT
- RET
-
-
- ; charactor or zero = csts();
-
- CSTS_: MOV AH,DIRECT_CODE ;CODE FOR DIRECT CONSOLE IO
- MOV DL,0FFH ;WANT A CHAR
- INT IBM
- MOV LASTCH,AL ;SAVE CHARACTER
- MOV AH,0 ;MAKE AN INT
- RET
-
-
- ; co(character);
-
- CO_: POP AX ;RETURN ADDRESS
- POP DX
- PUSH DX
- PUSH AX
- MOV AH,DIRECT_CODE ;WANT A DIRECT CONSOLE OUTPUT
- INT IBM
- RET
-
-
-
-
- ; MEMORY MANAGEMENT FUNCTIONS: _MEMORY, _SHOWSP, _SETSP
-
- PUBLIC _MEMORY_,_SETSP_,_SHOWSP_
-
- _MEMORY_:MOV AX,MEMFROM ;ADDRESS OF FIRST FREE BYTE OF MEMORY
- RET
-
- _SHOWSP_:POP DX ;RETURN ADDRESS
- MOV AX,SP ;RETURN SP VALUE TO USER
- JMP DX
-
- _SETSP_:
- POP DX ;CHOP THE STACK - DANGEROUS OPERATION
- POP BX ;NEW SP VALUE
- CMP BP,SP ;ANY LOCALS
- JNZ NOC
- MOV BP,BX ;MUST MOVE THE BP TOO
- NOC: MOV SP,BX
- PUSH BX
- JMP DX
-
-
- ; SEGMENT REGISTER FUNCTIONS: _SHOWDS, _SHOWCS, _SETDS
-
- PUBLIC _SHOWDS_,_SHOWCS_,_SETDS_
-
- _SHOWDS_:MOV AX,DS ;DS (AND SS) VALUE
- RET
-
- _SHOWCS_:MOV AX,CS ;CS VALUE
- RET
-
- _SETDS_:POP DX ;RETURN VALUE
- POP DS ;NEW DS
- PUSH DS
- JMP DX ;RETURN
-
-
-
-
- ; OS CALL USED BY OPEN, CREAT ETC.
-
- ; VALUE=_OS(CODE,ARGUMENT);
-
- PUBLIC _OS_
- _OS_: PUSH BP
- MOV BP,SP
- MOV AH,[BP+4] ;IBM CODE
- MOV DX,[BP+6] ;ARGUMENT POINTER
- INT IBM
- MOV AH,0 ;MAKE RETURN AN INTEGER
- POP BP
- RET
-
-