home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
msjournl
/
msjv3_6.arc
/
EMBEDDED.ARC
/
EMBEDDED.TXT
Wrap
Text File
|
1988-11-10
|
12KB
|
399 lines
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 */
}