;====================================================================
; Steinis Mini Compiler
; (c)Copyright 2002 by Sebastian Steinhauer
; steini@steini-welt.de
;====================================================================
; Diese Datei enthält alle wichtigen Startup-Codes und Prozeduren.
; Viele sind es ja noch nicht ;)
; Ein herzliches Dankeschön geht an Michael Tischer für seinen guten
; COM-Startup-Code. *g*
;====================================================================
; Letzte Änderung: 15:05 28.06.2002
; by Steini
;
; 15:04 28.06.2002
;	- neuer COM-Startup-Code eingebaut.
;	- nicht benötigter Speicher wird freigegeben
;	- Programmabhängige reservierung von Stack-Speicher
;====================================================================

stack_size	equ 1024	; Wird vom Compiler gesetzt!
pstack_size	equ stack_size/16+1


;====================================================================
ORG     0x100                   ; Wir erzeugen eine DOS-Datei (.COM)
start:
        mov     dx,cs           ; CS, DS und ES auf CS setzen, da wir                  
        mov     ds,dx           ; momentan eh nur COM-Dateien erzeugen.
        mov     es,dx
	jmp	short mem_init	; Wir initialisieren den Speicher
	
prog_start:			; Hier beginnt jetzt das Hauptprogramm
	call	__main		; Hauptprogramm aufrufen

prog_halt:			; Wir geben unseren Stackspace wieder frei
	mov	ah,0x49		; Freigabe von Speicher
	push	ss		; Im ES-Register wird der Platz übergeben
	pop	es
	int	0x21		; Speicher freigegeben

prog_quit:			; Hier wird das Programm beendet!
        mov     ax,0x4c00       ; Ok. Wir sind fertig. Programm wird beendet.
        int     0x21            ; UND SERVUS! Hoffentlich lief das Programm

;====================================================================
	db      'Steinis Mini Compiler 0.0.1'
mem_fail_msg:	db "ERROR: Can't allocate stack space!$"


;====================================================================
mem_init:			; Wir initialisieren den Hauptspeicher
	mov	ah,0x4a		; Wir wollen die Speichergröße ändern
	mov	bx,prog_ende	; Den gesamten Speicher hinter dem Programm
				; freigeben.
	add	bx,15		; Auf den nächsten Paragraphen aufrunden.
	mov	cl,4		; Adresse in Paragraphen umrechnen
	shr	bx,cl
	inc	bx
	int	0x21		; DOS-Aufrufen
	
	mov	ah,0x48		; Wir wollen jetzt den Stackspeicher
	mov	bx,pstack_size	; initialisieren.
	int	0x21		; DOS-Aufrufen
	jc	fail@mem_init	; Fehler in der Speicherreservierung!!!
	
	cli			; Interrupts sperren
	mov	ss,ax		; Neuen Stack setzen
	mov	sp,stack_size		
	sti			; Interrupts wieder erlauben
	
	jmp	short prog_start	; Programm starten

fail@mem_init:
	mov	ah,9		; Fehlermeldung!
	mov	dx,mem_fail_msg
	int	0x21
	jmp	short prog_quit	; Programm beenden

;====================================================================
__main:
	push	String0
	call	_conout

	push	String1
	push	String0
	call	_strcat

	push	String0
	call	_conout
	ret
String0:	dw 27
		db "Dies ist ein Test-String!",13,10
		db "                                                                     "
String1:	dw 17
		db " StrCat Test :)",13,10
;====================================================================
; int conout(string)
; gibt einen String über DOS aus
; (Es wird die Stringdefinition aus string.txt angenommen!)
_conout:
	push	bp
	mov	bp,sp
	mov	dx,[bp+4]		; Pointer des Strings
	push	dx			; Pointer übergeben
	call	_strlen			; Länge des Strings
	mov	cx,ax			; Länge in CX übergeben
	add	dx,2			; Anfang des Strings
	mov	bx,1			; Handle 1 (conout!)
	mov	ah,0x40			; Handle-Write
	int	0x21			; DOS
	pop	bp
	ret	2			; Zurück und 2 Byte weg

_strlen:
	push	bp
	mov	bp,sp		;Stack sichern
	mov	bx,[bp+4]	;Hole Pointer zum String
	mov	ax,[bx]		;1. Word ist Stringlänge!
	pop	bp		;BP holen
	ret	2		;des wars

_strcat:
	push	bp
	mov	bp,sp

	;push	[bp+4]		;Länge des 1. Strings ermitteln
	mov	dx,[bp+4]
	push	dx
	call	_strlen		;
	push	ax		;Länge zwischenspeichern ;)
	;push	[bp+6]		;Länge des 2. Strings ermitteln
	mov	dx,[bp+6]
	push	dx
	call	_strlen		;
	pop	cx		;CX=strlen(1), AX=strlen(2)

	mov	di,[bp+4]	;Pointer zu 1. String holen
	add	[di],ax		;String länger machen :)
	add	di,cx		;Pointer zum Ende des Strings
	add	di,2		;+Word beachten
	mov	cx,ax		;Jetzt Länge vom 2. String
	mov	si,[bp+6]	;Pointer für 2. String
	add	si,2		;Word wegnehmen
	rep	movsb		;String kopieren

	pop	bp
	ret	4
;====================================================================
prog_ende: