ANHANG A: .RUN PROGRAMM BEISPIEL

Abschnitt 3.6.3 hebt die wichtigsten Entwicklungsbedingungen hervor, die zu berücksichtigen sind wenn man .RUN Programme schreibt.

Auf der Emulator-Diskette befinden sich folgende Dateien:

RNRN.ASMAssembler .RUN Programm
MAIN.CC .RUN Programm Beispiel
RU_C.ASMC Header
Build.BATErzeugt Programm unter Verwendung von Turbo C Tools

Die obigen Dateien illustrieren zwei Programme die Atari Portfolios .RUN Funktion verwenden.

RNRN ist ein Assemblerprogramm das die ursprünglichen Aufrufparameter und dann drei Zahlen ausgibt.

MAIN illustriert ein in C geschriebenes .RUN Programm. RU_C.ASM ist der nötige „C“ Header für Borlands Turbo C Compiler und BUILD.BAT illustriert wie man das Programm mit Turbo C Tools erzeugt.

Bemerkungen bezüglich der Verbindung zwischen „C“ Dateien und dem RUN Befehl:

Für „C“ Dateien müssen wesentlich mehr Segmente deklariert werden damit „C“ den Code und die Daten an die richtigen Stellen in der .RUN Datei bekommt. Die .COM Datei wird durch Umbenennung in eine .RUN Datei gewandelt.

RU_C.ASM ist der Header der für die Verbindung zu einem „C“ Programm verwendet werden kann. Wenn „C“ Quelldateien ohne die entsprechenden Bibliotheken verwendet werden, kann die Datei R_CU direkt als Header benutzt werden. Falls Code aus Bibliotheken nötig ist, so muss der Header um die nötigen Initialisierungen erweitert werden.

Der RU_C.ASM Header funktioniert mit Turbo C und kann als Leitfaden zur Modifikation anderer „C“ Header verwendet werden, die bei den unterschiedlichen „C“ Compliler Bibliotheken vorkommen.

Die meisten „C“ Header die mit „C“ Compilern geliefert werden können für verschiedene Speichermodelle assembliert werden. Der Beispiel-Code in RU_C.ASM muss in dem „C“ Startup Header stehen und muss für SMALL model assembliert werden.

Kontaktieren sie Atari bezüglich RUN Startup Codes für die unterschiedlichen C Compiler.



TITLE	RNRN.ASM
 
comment	*
	(c) Copyright DIP, 1989
 
	Example .RUN program
 
	For Appendix 1 of DIP Pocket PC Technical Reference Manual
 
	*
 
DGROUP	group	_text,_data,_cdata
 
STACKSIZE	equ	400		; byte in stack.
 
; code segment.
_text	segment	public byte 'CODE'
	assume	cs:_text,ds:_data
 
	org	0			; IP is 0 on entry.
 
;***********************************************************************;
; rnrn_main								;
;									;
; RUN command test routine.						;
; On entry, DS, SS and ES all point to the PSP in RAM.			;
; CS is a ptr into the credit card, so may actually be in ROM!		;
; When this routine is executed, the whole of RAM is allocated to the	;
; process.								;
;									;
; Parameters:								;
;	None								;
; Returns:								;
;	None								;
;***********************************************************************;
 
rnrn_main	proc	near
 
	mov	bx,10h			; 10h paras to keep the PSP.
	mov	ah,04ah			; modify memory.
	int	21h
	jc	rnrn_err		; error reducing memory.
 
	mov	bx,OFFSET rnrn_uend	; alloc for initialised data,
	sub	bx,OFFSET rnrn_dstart	; uninitialised data and a
	add	bx,0fh				; stack.
	mov	cl,4
	shr	bx,cl			; calc paras in init data area.
	add	bx,STACKSIZE/16		; add in paras in stack.
	mov	ah,48h			; allocate memory.
	int	21h			; allocate stack and data.
	jc	rnrn_err		; no memory.
 
	mov	ss,ax			; set stack to point to RAM.
	mov	sp,OFFSET rnrn_uend+STACKSIZE
 
	push	es			; preserve PSP pointer.
 
	mov	cx,OFFSET rnrn_dend
	sub	cx,OFFSET rnrn_dstart	; bytes in initialised data.
 
	mov	si,OFFSET DGROUP:rnrn_dstart	; copy from here.
	push	cs
	pop	ds			; source is on memory card.
	xor	di,di
	mov	es,ax			; target is allocated RAM.
	cld
 
	rep	movsb			; copy init data from card to RAM.
 
	pop	es			; restore PSP ptr.
 
	mov	si,5dh
	mov	cx,11
 
rnrn_fcb1:
	mov	dl,es:[si]		; get char from FCB built into PSP.
	inc	si
	mov	ah,2
	int	21h			; print name of first parsed FCB.
	loop	rnrn_fcb1
 
	mov	si,6dh
	mov	cx,11
 
rnrn_fcb2:
	mov	dl,es:[si]
	inc	si
	mov	ah,2
	int	21h			; print name of second parsed FCB.
	loop	rnrn_fcb2
 
	push	ss
	pop	ds			; DS is ptr to data in RAM.
 
	mov	al,_rnrn_val		; get initialised data.
	call	rnrn_disp		; display the value.
 
	inc	_rnrn_val
 
	mov	al,_rnrn_val		; get changed data.
	call	rnrn_disp		; display the value.
 
	mov	rnrn_unin,44		; set a piece of uninitialised data.
	mov	al,rnrn_unin		; get uninitialised data.
	call	rnrn_disp		; display the value.
 
	xor	al,al			; return errorlevel of 0.
	jmp	short rnrn_end
 
rnrn_err:
	mov	dx,OFFSET DGROUP:rnrn_mem
	push	cs
	pop	ds			; write directly from ROM card!
	mov	ah,9			; write string.
	int	21h			; tell user there was memory error.
	mov	al,1			; terminate with error code of 1.
 
rnrn_end:
	push	ax			; save errorlevel code in al.
 
	mov	ah,1			; wait for a key.
	int	21h
 
	pop	ax			; get errorlevel code back.
	mov	ah,4ch			; terminate process.
	int	21h
 
rnrn_main	endp
 
 
;***********************************************************************;
; rnrn_disp								;
;									;
; Display the value in AL with a trailing space.			;
;									;
; Parameters:								;
;	AL	Value to print, less than 100.				;
; Returns:								;
;	None								;
;***********************************************************************;
rnrn_disp	proc	near
	aam				; convert to two numbers.
	add	ax,3030h		; convert to ASCII digits '0'..'9'.
	push	ax			; save to print 2nd char.
 
	mov	dl,ah
	mov	ah,2			; print 1st digit.
	int	21h
 
	pop	dx
	mov	ah,2			; print 2nd digit.
	int	21h
 
	mov	dl,' '
	mov	ah,2			; print a space.
	int	21h
 
	ret
rnrn_disp	endp
 
_text	ends
 
 
; initialised and uninitialised RAM data.
; this is para since the segment will start at zero when it is copied
; over into RAM.
_data	segment	public para 'data'
rnrn_dstart	label	byte
 
	public	_rnrn_val
_rnrn_val	db	42
 
rnrn_dend	label	byte
rnrn_ustart	label	byte		; uninitialised data start.
 
rnrn_unin	db	?
 
rnrn_uend	label	byte		; uninitialised data end.
; the stack is added on here, after initialised and uninitialised data.
_data	ends
 
 
_cdata	segment	public byte 'data'
 
; initialised data which doesn't get transferred to RAM.
rnrn_mem	db	"Out of memory$"
 
_cdata	ends
	end	rnrn_main








/*	MAIN.C
 
	Copyright DIP Ltd, 1989
 
	DIP Pocket PC RUN file 'C' interface main program.
*/
 
char buf[2];			/* this is BSS, unitialised. */
 
char *str="Hello world";	/* this is _DATA, initialised. */
 
unsigned int __brklvl;		/* required by Turboc library. */
 
int main()
    {
    puts(str);			/* print initialised hello. */
 
    buf[0]='!';			/* initialise uninitialised data. */
    buf[1]=0;
 
    puts(&buf[0]);		/* print uninitialised data. */
 
    return(0);
    }
 
void _exit()
/*
Dummy exit function required for the Turboc libraries.
*/
{}








TITLE	RU_C.ASM
 
comment	*
	Copyright DIP Ltd., 1989
 
	'C' header for creation of DIP Pocket PC .RUN files.
 
	Memory usage:
 
	-------------------------------------------- High memory -------
	SP:		Stack
	----------------------------------------------------------------
			Uninitialised data
	----------------------------------------------------------------
	DS/SS:		Initialised data
	----------------------------------------------------------------
	ES:		PSP
	-------------------------------------------- Low memory --------
	*
 
;       Segment and Group declarations
 
; code and fixed data (less than 64k).
_TEXT   SEGMENT BYTE PUBLIC 'CODE'
_TEXT   ENDS
 
; code ends (marker segment)
_TEXTEND   SEGMENT BYTE PUBLIC 'CEND'
_TEXTEND   ENDS
 
; initialised data transferred into RAM.
_DATA   SEGMENT PARA PUBLIC 'DATA'
_DATA   ENDS
 
; uninitialised data which is allocated space in RAM.
_BSS    SEGMENT WORD PUBLIC 'BSS'
_BSS    ENDS
 
; uninitialised data end (marker segment).
_BSSEND SEGMENT BYTE PUBLIC 'STACK'
_BSSEND ENDS
 
DGROUP GROUP _DATA,_BSS,_BSSEND		; dgroup is all data segments.
 
        ASSUME  CS:_TEXT, DS:DGROUP
 
	extrn	_main:near		; main 'C' routine.
 
STACKSIZE	equ	128		; stack size in bytes.
 
; At the start, SS, DS and ES all point to the program segment prefix.
; CS is a ptr into the memory card.
 
_TEXT   SEGMENT
 
	org	0			; ip is zero on entry.
 
start	proc	near			; near is irrelevant, use fn 4c to
					; terminate.
 
	mov	dx,ds			; ensure DS:0 is ptr to 1st data byte.
	add	dx,10h
	mov     ds,dx
 
	mov	bx,STACKSIZE
	add	bx,offset DGROUP:edata	; bx has bytes of reqd RAM.
 
	push	bx			; this will be stack ptr.
 
	shr	bx,1
	shr	bx,1
	shr	bx,1
	shr	bx,1
	add	bx,11h			; 10h for PSP, 1 for rounding.
 
	mov	ah,4ah
	int	21h			; reduce RAM to required RAM.
	jc	abort			; can't reduce.
 
	pop	bx			; get calc'd p back.
	mov	ax,ds
	mov	ss,ax			; stack is in RAM.
	mov	sp,bx
 
	push	ds
	pop	es			; target is allocated RAM after PSP.
 
	push	cs
	pop	ds			; source is memory card.
 
	mov	si, offset _TEXT:etext	; get ptr to last byte in code.
	add	si, 0Fh			; round up to 1st byte in data.
	and	si, 0FFF0h		; data is para aligned on the card.
					; ds:si is ptr to start of init data.
	xor	di,di			; put data at 0 offs into alloc'd RAM.
					; es:di is ptr to alloc'd RAM target.
	mov	cx, offset DGROUP:bdata	; get bytes in initialised data.
	inc	cx			; round up: ensure last byte is copied.
	shr	cx,1
 
	cld
	rep	movsw			; copy init data from memory card.
 
	push	es
	pop	ds			; DS back to ptr to RAM.
 
	mov	di,offset DGROUP:bdata	; ptr to where uninit data goes in RAM.
	mov	cx,offset DGROUP:edata	; ptr to end of all data.
	sub	cx,di			; calc bytes in BSS.
	xor	al,al			; clear to zero.
	rep	stosb
 
	call	_main			; invoke program.
 
	mov	ah,4ch			; terminate with main's return code.
	int	21h
 
abort:
	mov	ax,4c01h		; abort with error.
	int	21h
start	endp
 
_TEXT	ENDS
 
 
_TEXTEND   SEGMENT BYTE PUBLIC 'CEND'
etext	label	byte		;Last byte of text segment
_TEXTEND   ENDS
 
_DATA   SEGMENT
	public	_errno
_errno	dw	0
_DATA   ENDS
 
_BSS    SEGMENT
bdata	label   byte
_BSS    ENDS
 
_BSSEND SEGMENT
edata	label   byte
_BSSEND ENDS
 
	end	start