home *** CD-ROM | disk | FTP | other *** search
- Figure 2
-
- Sample Microsoft C Start-Up Routine for Embedded Applications
-
- NAME STARTUP_CODE
- ; THIS IS A SAMPLE START-UP PROGRAM FOR AN EMBEDDED SYSTEM.
- ; THE MEMORY LAYOUT CONFORMS TO THE NAMING CONVENTION USED
- ; IN MICROSOFT C, VERSION 4.X AND 5.X.
- ; THIS ASSEMBLY FILE SHOULD BE ASSEMBLED USING MICROSOFT
- ; MASM ASSEMBLER USING THE FOLLOWING COMMAND, ASSUMING THIS
- ; FILE IS CALLED STARTUP.ASM:
- ; >MASM STARTUP/MX,STARTUP,STARTUP,NUL
- ; THE /MX OPTION IS USED TO PRESERVE LOWER-CASE IN PUBLIC
- ; AND EXTERNAL NAMES.
- ;
- ; SETUP OF SEGMENT CLASSES IN MICROSOFT C 5.X PROGRAMS.
- ;
- ; HIGH ADDRESS
- ; - -------------
- ; | |'BOOTSTRAP'|
- ; | -------------
- ; | : :
- ; | : :
- ; R ------------- ---THESE TWO CLASSES ARE TO BE
- ; O | 'CONST' | ^ COPIED TO THEIR RAM
- ; M ------------- | LOCATIONS AT POWER-UP
- ; | | 'DATA' | v
- ; | ------------- <---ROMCODE_END SEGMENT
- ; | | 'CODE' |
- ; - ------------- <---ROMCODE_BEG SEGMENT
- ; : :
- ; : :
- ; - ------------- <---UDATA_END SEGMENT
- ; | | 'STACK' |
- ; | -------------
- ; | | 'BSS' |
- ; | ------------- <---IDATA_END & UDATA_BEG
- ; | | 'CONST' | ^ SEGMENTS
- ; R ------------- |--THESE TWO CLASSES ARE TO BE ; A | 'DATA' | v INITIALIZED BY START-UP
- ; M ------------- <-- ROUTINE AT POWER-UP
- ; | : : |
- ; | : : |-IDATA_BEG SEGMENT
- ; | -------------
- ; | | 'INT_PTR' |
- ; - -------------
- ; LOW ADDRESS
- ;
- ; CHOOSE THE MEMORY MODEL BY SETTING THE APPROPRIATE LABEL
- ; TO 1.
- ;
- SMALL EQU 0
- COMPACT EQU 0
- MEDIUM EQU 0
- LARGE EQU 1
- HUGE EQU 0
- STACK_SIZE EQU 400H ; RESERVE 1K WORD OF STACK OR ANY SIZE YOU WANT
- __acrtused EQU 1 ; IT IS USED TO SATISFY THE EXTERNAL REFERENCE
- ; FOUND IN EVERY OBJECT FILE GENERATED
- ; BY THE MICROSOFT C COMPILER, VER 5.X
- PUBLIC __acrtused ; THE SYMBOL HAS TO BE IN LOWER-CASE
-
- DGROUP GROUP IDATA_BEG,_DATA,CONST,IDATA_END,UDATA_BEG,_BSS,STACK,UDATA_END
-
- ;THIS SEGMENT MARKS THE BEGINNING OF ROM CODE
- ROMCODE_BEG SEGMENT PARA 'ROMCODE_BEG'
- ROMCODE_BEG ENDS
-
- IF SMALL OR COMPACT
- _TEXT SEGMENT BYTE PUBLIC 'CODE'
- EXTRN _main:NEAR ;C main()
- ASSUME CS:_TEXT
- ENDIF
- IF MEDIUM OR LARGE OR HUGE
- EXTRN _main:FAR ;C main()
- STARTUP_TEXT SEGMENT BYTE PUBLIC 'CODE'
- ASSUME CS:STARTUP_TEXT
- ENDIF
- ASSUME DS:DGROUP, SS:DGROUP
- PUBLIC START
- START:
- START_I2ICE LABEL BYTE ; ADDRESS LABEL FOR INTEL I2ICE
- CLI
- CLD
- ; ************************************************************
- ; *** YOUR CODE HERE TO DO HARDWARE INITIALIZATION
- ; AND RAM CHECK ***
- ************************************************************
- PUBLIC INIT_RAM_DATA
- INIT_RAM_DATA:
- INIT_RAM_DATA_I2ICE LABEL BYTE ; ADDRESS LABEL FOR INTEL
- ; I2ICE
- ; *** TRANSFER INITIALIZATION DATA FROM ROM TO RAM ***
- ; COMPUTE THE SIZE OF 'DATA' AND 'CONST' CLASS IN NO. OF PARAGRAPHS:
-
- MOV AX,SEG IDATA_END ; FRAME NO. OF IDATA_END SEGMENT
- ; = END OF 'CONST' CLASS IN RAM
- MOV BX,SEG IDATA_BEG ; FRAME NO. OF IDATA_BEG SEGMENT
- ; = START OF 'DATA' CLASS IN RAM
- SUB AX,BX ; AX = SIZE OF 'DATA' & 'CONST' CLASSES
- MOV CL,3 ; SET UP TO MULTIPLE BY 8
- SHL AX,CL ; COMPUTE NO. OF WORDS TO BE TRANSFERRED
- MOV CX,AX ; TRANSFER COUNTER
- JCXZ NO_IDATA_DATA
-
- ; OBTAIN THE FRAME NO. OF 'DATA' CLASS PLACED IN ROM
-
- MOV AX,SEG ROMCODE_END ; FRAME NO. OF ROMCODE_END SEGMENT
- ; = BEGINNING OF 'DATA' CLASS IN ROM
- MOV DS,AX ; SOURCE STRING
- MOV SI,0
-
- ; OBTAIN THE FRAME NO. OF 'DATA' CLASS LOCATED IN RUN-TIME RAM SPACE
-
- MOV AX,SEG IDATA_BEG ; FRAME NO. OF IDATA_BEG SEGMENT
- ; = BEGINNING OF 'DATA' CLASS IN RAM
- MOV ES,AX ; DESTINATION STRING
- MOV DI,0
-
- ; INITIALIZE THE 'DATA' AND 'CONST' CLASSES IN
- ; RUN-TIME RAM SPACE
-
- REP MOVSW ; BEGIN WORD TRANSFER
- PUBLIC NO_IDATA_DATA
- NO_IDATA_DATA:
- NO_IDATA_DATA_I2ICE LABEL BYTE ; ADDRESS LABEL FOR
- ; INTEL I2ICE
-
- ; *** CLEAR UNINITIALIZED DATA ***
- ; COMPUTE THE SIZE OF 'BSS' & 'STACK' CLASSES IN NO. OF
- ; PARAGRAPHS:
-
- MOV AX,SEG UDATA_END ; FRAME NO. OF UDATA_END SEGMENT
- ; = END OF 'STACK' CLASS IN RAM
- MOV BX,SEG UDATA_BEG ; FRAME NO. OF UDATA_BEG SEGMENT
- ; = START OF 'BSS' CLASS IN RAM
- SUB AX,BX ; AX = SIZE IN PARAGRAPHS
- MOV CL,3 ; SET UP TO MULTIPLE BY 8
- SHL AX,CL ; COMPUTE NO. OF WORDS TO BE INITIALIZED
- MOV CX,AX ; SETUP COUNTER
- JCXZ NO_UDATA
- MOV ES,BX ; SETUP DESTINATION POINTER
- MOV DI,0
- MOV AX,0 ; INITIALIZE TO 0
- REP STOSW
- PUBLIC NO_UDATA
- NO_UDATA:
- NO_UDATA_I2ICE LABEL BYTE ; ADDRESS LABEL FOR INTEL I2ICE
-
- ; *** SETUP DATA AND STACK SEGMENT ***
-
- MOV AX,DGROUP
- MOV DS,AX ; SETUP DATA SEGMENT
- MOV SS,AX ; SETUP STACK POINTER
- MOV SP,OFFSET DGROUP:STACK_TOP
- STI ; ENABLE INTERRUPT NOW
- JMP _main ; ENTER C main() FUNCTION
- HLT
- IF SMALL OR COMPACT
- _TEXT ENDS
- ENDIF
- IF MEDIUM OR LARGE OR HUGE
- STARTUP_TEXT ENDS
- ENDIF
-
- ;THIS SEGMENT MARKS THE END OF ROM CODE
- ROMCODE_END SEGMENT PARA 'ROMCODE_END'
- ROMCODE_END ENDS
-
- ; *** THE FOLLOWING SEGMENTS ARE ALL LOCATED IN RAM ***
-
- INT_PTR SEGMENT AT 0H ;'INT_PTR'
- ;INTERRUPT POINTER TABLE, LOCATE AT 0H IN RAM.
- PUBLIC TYPE_0,TYPE_1,TYPE_2,TYPE_3,TYPE_4,TYPE_32
- TYPE_0 DD ? ;DIVIDE-ERROR
- TYPE_1 DD ? ;SINGLE-STEP
- TYPE_2 DD ? ;NON-MASKABLE INTERRUPT
- TYPE_3 DD ? ;BREAKPOINT
- TYPE_4 DD ? ;OVERFLOW
- ;SKIP INTEL RESERVED VECTORS
- ORG 32 * 4
- TYPE_32 DD ? ;MAY PLACE YOUR VECTORS HERE
- ;MORE INTERRUPT VECTORS
- INT_PTR ENDS
-
- ; THIS SEGMENT MARKS THE BEGINNING OF DGROUP AND INITIALIZED DATA IN RAM
- IDATA_BEG SEGMENT PARA PUBLIC 'IDATA_BEG'
- IDATA_BEG ENDS
-
- _DATA SEGMENT WORD PUBLIC 'DATA'
- _DATA ENDS
-
- CONST SEGMENT WORD PUBLIC 'CONST'
- CONST ENDS
-
- ; THIS SEGMENT MARKS THE END OF INITIALIZED DATA IN RAM
- IDATA_END SEGMENT PARA PUBLIC 'IDATA_END'
- IDATA_END ENDS
-
- ; THIS SEGMENT MARKS BEGINNING OF UNINITIALIZED DATA IN RAM
- UDATA_BEG SEGMENT PARA PUBLIC 'UDATA_BEG'
- UDATA_BEG ENDS
-
- _BSS SEGMENT WORD PUBLIC 'BSS'
- _BSS ENDS
-
- STACK SEGMENT PARA STACK 'STACK'
- DW STACK_SIZE DUP (?)
- STACK_TOP LABEL WORD
- STACK ENDS
-
- ; THIS SEGMENT MARKS THE END OF UNINITIALIZED DATA IN RAM
- UDATA_END SEGMENT PARA PUBLIC 'UDATA_END'
- UDATA_END ENDS
-
- ; THIS SEGMENT CONTAINS BOOTSTRAP CODE AT HARDWARE RESET OR ; POWER-UP
- ; FAR JUMP TO PROGRAM START, LOCATE AT FFFF0H IN ROM.
- BOOTSTRAP SEGMENT AT 0FFFFH ;'BOOTSTRAP'
- JMP FAR PTR START
- BOOTSTRAP ENDS
- END START
-
-
-
-
-
-
-
-
- Extra Figure (not used in article)
-
- Example of a Locator Map File
-
-
- REX 8086/8087/8088/80186 OBJECT CODE LOCATER, V5.0
- TIME: 14:55:23 08-10-1988
-
- INPUT FILES: SAMPLE.LNK
- OUTPUT FILE: SAMPLE.ABS
- CONTROLS SPECIFIED IN INVOCATION COMMAND:
- ORDER(CLASSES(IDATA_BEG,DATA,CONST,IDATA_END,
- UDATA_BEG,BSS,STACK,FAR_BSS,UDATA_END,
- DEBSYM,DEBTYP,
- ROMCODE_BEG,CODE,ROMCODE_END))
- ADDRESSES(CLASSES(IDATA_BEG(200H),
- DEBSYM(20000H),
- ROMCODE_BEG(0E0000H)))
- NOINITCODE
-
- SYMBOL TABLE OF MODULE startup
- BASE OFFSET TYPE SYMBOL BASE OFFSET TYPE SYMBOL
- E000H 0002H PUB INIT_RAM_DATA E000H 0024H PUB NO_IDATA_DATA
- E000H 003EH PUB NO_UDATA E000H 0000H PUB START
- 0000H 0000H PUB TYPE_0 0000H 0004H PUB TYPE_1
- 0000H 0008H PUB TYPE_2 0000H 000CH PUB TYPE_3
- 0000H 0080H PUB TYPE_32 0000H 0010H PUB TYPE_4
- 0000H 0001H PUB __acrtused 0020H 0008H PUB _count
- 0020H 0000H PUB _in_ptr E005H 0000H PUB _main
- 0020H 0004H PUB _out_ptr 00A1H 0080H PUB _picmask
- E005H 0086H PUB _process_data 00A1H 0000H PUB _ring_buf
- E005H 0092H PUB _sio_handler
-
- MODULE = startup
- BASE OFFSET TYPE SYMBOL BASE OFFSET TYPE SYMBOL
- E000H 0000H LIN 77 E000H 0001H LIN 78
- E000H 0002H LIN 88 E000H 0005H LIN 90
- E000H 0008H LIN 92 E000H 000AH LIN 93
- E000H 000CH LIN 94 E000H 000EH LIN 95
- E000H 0010H LIN 96 E000H 0012H LIN 100
- E000H 0015H LIN 102 E000H 0017H LIN 103
- E000H 001AH LIN 107 E000H 001DH LIN 109
- E000H 001FH LIN 110 E000H 0022H LIN 114
- E000H 0024H LIN 122 E000H 0027H LIN 124
- E000H 002AH LIN 126 E000H 002CH LIN 127
- E000H 002EH LIN 128 E000H 0030H LIN 129
- E000H 0032H LIN 130 E000H 0034H LIN 131
- E000H 0036H LIN 132 E000H 0039H LIN 133
- E000H 003CH LIN 134 E000H 003EH LIN 141
- E000H 0041H LIN 142 E000H 0043H LIN 143
- E000H 0045H LIN 144 E000H 0048H LIN 145
- E000H 0049H LIN 146 E000H 004EH LIN 147
- FFFFH 0000H LIN 208
-
- MODULE = main
- BASE OFFSET TYPE SYMBOL BASE OFFSET TYPE SYMBOL
- E005H 0000H LIN 27 E005H 0018H LIN 28
- E005H 001FH LIN 30 E005H 002FH LIN 31
- E005H 0047H LIN 32 E005H 004BH LIN 33
- E005H 0065H LIN 34 E005H 006FH LIN 35
- E005H 0083H LIN 37 E005H 0086H LIN 41
- E005H 0089H LIN 43 E005H 0090H LIN 44
- E005H 0092H LIN 47 E005H 00A4H LIN 48
- E005H 00A5H LIN 49 E005H 00AEH LIN 50
- E005H 00C8H LIN 51 E005H 00D2H LIN 52
- E005H 00DAH LIN 53 E005H 00DEH LIN 54
- E005H 00E3H LIN 55
-
- MEMORY MAP OF MODULE startup
- MODULE START ADDRESS PARAGRAPH = E000H OFFSET = 0000H
-
- SEGMENT MAP
- START STOP LENGTH ALIGN NAME CLASS OVERLAY
- 00000H 00083H 0084H A INT_PTR
- 00200H 00200H 0000H G IDATA_BEG IDATA_BEG
- 00200H 00209H 000AH W _DATA DATA
- 0020AH 0020BH 0002H W CONST CONST
- 00210H 00210H 0000H G IDATA_END IDATA_END
- 00210H 00210H 0000H G UDATA_BEG UDATA_BEG
- 00210H 00210H 0000H W _BSS BSS
- 00210H 00A0FH 0800H G STACK STACK
- 00A10H 00A90H 0081H G FAR_BSS_1 FAR_BSS
- 00AA0H 00AA0H 0000H G UDATA_END UDATA_END
- 20000H 20074H 0075H G $$SYMBOLS DEBSYM
- 20075H 200F6H 0082H B $$SYMBOLS DEBSYM
- 20100H 2010BH 000CH G $$TYPES DEBTYP
- 2010CH 20197H 008CH B $$TYPES DEBTYP
- E0000H E0000H 0000H G ROMCODE_BEG ROMCODE_BEG
- E0000H E004EH 004FH B STARTUP_TEXT CODE
- E0050H E013DH 00EEH W MAIN_TEXT CODE
- E0140H E0140H 0000H G ROMCODE_END ROMCODE_END
- FFFF0H FFFF4H 0005H A BOOTSTRAP
-
- GROUP MAP
- ADDRESS GROUP OR SEGMENT NAME
- 00200H DGROUP
- IDATA_BEG\\IDATA_BEG\\
- _DATA\\DATA\\
- CONST\\CONST\\
- IDATA_END\\IDATA_END\\
- UDATA_BEG\\UDATA_BEG\\
- _BSS\\BSS\\
- STACK\\STACK\\
- UDATA_END\\UDATA_END\\
-
-
-
-
-
- Figure 6
-
- C Source for functions that implement a Ring Buffer
-
-
- /* To generate in-line 8086 opcodes for intrinsic functions,
- such as inp, outp, and _enable, specify /Oi in C compiler */
- #define RING_BUF_SIZ 128
- #define PICIER 0xC2
- #define PICEOI 0xC0
- #define IRQDIS 0x20
- #define EOI 0x20
- #define SIOPORT 0x10
- #define OUTPORT 0x12
- #define enable_sio() picmask = inp(PICIER); \\
- picmask &= (~IRQDIS); \\
- outp(PICIER, picmask);
- #define disable_sio() picmask = inp(PICIER); \\
- picmask |= IRQDIS; \\
- outp(PICIER, picmask);
- char ring_buf[RING_BUF_SIZ];
- char *in_ptr = ring_buf;
- char *out_ptr = ring_buf;
- int count = 0;
- char picmask;
- void process_data(char);
-
- main()
- {
- while(1)
- {
- enable_sio(); /* enable serial i/o */
- if (count > 0)
- {
- process_data(*out_ptr);
- disable_sio(); /* disable serial i/o */
- count--;
- if (out_ptr++ == ring_buf + RING_BUF_SIZ)
- out_ptr = ring_buf; /* ring buffer */
- enable_sio(); /* enable serial i/o */
- }
- }
- }
-
- void process_data(c)
- char c;
- {
- outp(OUTPORT, c);
- }
-
- void interrupt far sio_handler()
- {
- _enable(); /* enable higher order interrupt */
- *in_ptr = inp(SIOPORT);
- if (in_ptr++ == ring_buf + RING_BUF_SIZ)
- in_ptr = ring_buf;
- if (count != RING_BUF_SIZ)
- count++;
- outp(PICEOI, EOI); /* reset interrupt */
- }
-
-