1             7 @ @ @ @ @ C:\WORD\STANDARD.DFV                                                STARNL  A                     AUTOASK

Das Programm AUTOASK.COM entstand aus der Notwendigkeit heraus, bei einem nicht besetzten Rechner im Netzwerk automatisch die Netz-Software zu laden, wenn er ferneingeschaltet wurde.

In die AUTOEXEC.BAT-Datei des unbesetzten Rechners wurden folgende Zeilen aufgenommen:
	...
	echo SOLL NETZWERK GELADEN WERDEN  J/N
	autoask
	if errorlevel 1 goto weiter
	Netz
	...
	:weiter
	...
Nach dem Ferneinschalten, das ber eine eigene Netzzuleitung erfolgte, lud der Rechner dann automatisch nach dem BOOTEN die Netz-Software. Wurde dieser Rechner hingegen fr eigene Anwendungen selbst hochgefahren, konnte das Laden durch Eingabe von N unterbunden werden, wodurch der gesamte Speicher fr die Anwender-Software zur Verfgung stand.


Nun zum Programm selbst. Das Source-Listing ist ziemlich ausfhrlich dokumentiert, deshalb sollen, vor allem fr ASSEMBLER-Neulinge, nur einige Schwerpunkte besprochen werden:

Da das Programm spter als .COM-Programm laufen soll, ist die ORG100h-Direktive erforderlich:
	ORG   100h	;jedes .COM-Programm beginnt an der
		;OFFSET-Adresse 0100h mit einem
		;ausfhrbaren Befehl

	ASSUME CS:CSEG,DS:CSEG,SS:CSEG,ES:CSEG

START  PROC  NEAR
	NOP	;Erster ausfhrbarer Befehl fr autoask.COM
	NOP
	NOP
	JMP  INIT1

Bei INIT wird zunchst berprft ob beim Aufruf von AUTOASK Parameter angegeben wurden. Als Parameter kommen eine ein- oder zweiziffrige Zahl oder das Fragezeichen in Frage. Alle brigen Zeichen werden ignoriert. Der Eingabepuffer beginnt bei 80h, wobei als erstes die Anzahl der im Anschlu an den Programmaufruf eingegebenen Zeichen steht (das abschlieende CARRIAGE RETURN wird dabei nie mitgezhlt!). Wurden keine Parameter angegeben, so wird bei INIT2 der vorgegebene Wert von 5 Sekunden (AH=0, AL=5) in den Speicherplatz fr die Verzgerungszeit DLY geladen. Wurde ? bergeben, so wird der HELP-Bildschirm angezeigt:

INIT1:	
MOV  SI,80h			;80h = Beginn des Kommandopuffers
	MOV  AL,[SI]	;Anzahl der Zeichen im Puffer (ohne abschlieendes CR)
	CMP  AL,0		;wenn 0 keine weitere Eingabe
	JE   INIT2

	XOR  AH,AH
	ADD  SI,AX	; = letztes Zeichen im Eingabepuffer (vor CR)
	MOV  AL,[SI]
	CMP  AL,"?"     	;bei ? Helpmen aufrufen und beenden
	JE   HELP

Nun erfolgt die berprfung, ob die eingegebenen Zeichen tatschlich Ziffern sind (mssen zwischen 30h und 39h liegen!). Ist dies nicht der Fall wird wieder mit der Standardeinstellung bei INIT2 fortgefahren. Bei einer gltigen Ziffer wird diese vom ASCII-Wert in den Dezimalwert (= Hexwert) umgewandelt und in der entsprechenden Speicherstelle (EINER bzw. ZEHNER) gespeichert. 

	CMP  AL,30h		;ASCII-Zahl 0 = 30h
	JC   INIT2		;wenn CARRY - keine Zahl
	CMP  AL,40h		;ASCII-Zahl 9 = 39h
	JNC  INIT2		;wenn noch kein CARRY, dann keine Zahl
	SUB  AL,30h		;ASCII-Zahl in Dezimalwert umwandeln
	MOV  EINER,AL	;Einerstelle sichern

	DEC  SI
	MOV  AL,[SI]
	CMP  AL,30h		;ASCII-Zahl 0 = 30h
	JC   INIT2		;wenn CARRY - keine Zahl
	CMP  AL,40h		;ASCII-Zahl 9 = 39h
	JNC  INIT2		;wenn noch kein CARRY, dann keine Zahl
	SUB  AL,30h		;ASCII-Zahl in Dezimalwert umwandeln
	MOV  ZEHNER,AL	;Zehnerstelle sichern

Die in EINER und ZEHNER gespeicherten Werte werden nun in AL addiert und als "Verzgerungszeit" in DLY gespeichert:

INIT2:
	MOV  AL,EINER		;Verzgerungszeit ermitteln: Fr jede
	MOV  AH,ZEHNER		;Zehnerstelle in AH werden 10 zu AL, in
IN2:	SUB  AH,1			;dem bereits die Einer stehen, addiert.
	JC   IN4
	ADD  AL,10
	JMP  IN2

IN4:	MOV  DLY,AL	;Verzgerungszeit in DLY

Bei INIT3 wird der Vektor (Interrupt-Adresse) des USER TIMER INTERRUPTS gesichert und auf die Adresse der AUTOASK-Routine umgeleitet. Fortan wird bei jedem Auftreten des USER TIMER INTERRUPTS (18,2 mal in der Sekunde) die Routine DELAY angesprungen, der Wert in COUNT um 1 verringert und der USER TIMER INTERRUPT an die ursprngliche Vektoradresse weitergereicht (JMP DWORD PTR CS:TIMER): 

DELAY:	STI		;Interrupts wieder zulassen
	PUSH DS
	PUSH CX
	PUSH CS
	POP  DS 		;da Einsprung ber INT Datensegment setzen
	MOV  CL,COUNT	;Timer-Interrupt kommt 18,2 mal pro Sekunde,
	DEC  CL		;nach 18 mal, also nach etwa 1 Sekunde ist
	JZ   DLY4		;CL und damit COUNT = Null geworden.
DLY2:MOV  COUNT,CL
	POP  CX
	POP  DS 		;altes Datensegment wiederherstellen
	JMP  DWORD PTR CS:TIMER

Ist COUNT schlielich Null geworden (nach 18 mal der Fall, entspricht etwa einer Sekunde) wird DLY um 1 verringert und, falls DLY noch nicht Null ist, der Zhler COUNT erneut mit dem Wert 18 geladen: 

DLY4:MOV  CL,DLY
	OR   CL,CL		;ist DLY schon Null ? Wenn nicht
	JZ   DLY6
	DEC  CL		;DLY um 1 verringern und COUNT wieder
	MOV  DLY,CL
DLY6:	MOV  CL,18		;auf 18 stellen fr neuen Durchgang
	JMP  DLY2

Nach dieser Installation wartet AUTOASK in der "Zeitschleife" solange, bis entweder der Wert in DLY Null geworden ist oder aber eine "gltige Taste" bettigt wurde. 

;********** ZEITSCHLEIFE ANFANG **********************************

BEGINN: BEEP
BEG2:MOV  AH,0Bh		;Wurde ein Zeichen ber Tastatur eingegeben?
	INT  21h		;Rckgabe:  AL = 00   kein Zeichen
	OR   AL,AL		;		  AL = FF   Zeichen verfgbar
	JNZ  EINGABE
	MOV  AL,DLY
	OR   AL,AL
	JZ   EIN2
	JMP  BEG2		;Solange, bis entweder eine Eingabe erfolgt
				;oder DLY Null geworden ist.

;********** ZEITSCHLEIFE ENDE ************************************

Gltige Zeichen bei der Eingabe sind nur J und N, wobei es gleichgltig ist, ob die Eingabe in Klein- oder Grobuchstaben (unterscheiden sich nur im Bit 5) erfolgt. Dies wird durch Setzen des Bits 5 (OR AL,00100000b) erreicht. Bit 5 ist bei Grobuchstaben ohnedies 1, bei Kleinbuchstaben wird es durch die ODER-Funktion auf 1 gesetzt.

EINGABE:
	MOV  AH,07h			;Console Char.Input ohne Echo, Zeichen in AL
	INT  21h
	OR   AL,00100000b		;Gro- in Kleinbuchstaben umwandeln
	CMP  AL,"j"
	JE   EIN2
	CMP  AL,"n"
	JE   EIN4
	JMP  BEGINN

EIN2:	MOV  ERR,0
	JMP  SHORT ENDE

EIN4:	MOV  ERR,1
	JMP  SHORT ENDE

Wurde J eingegeben oder ist die Zeit ohne Eingabe abgelaufen, wird ERR=0 gesetzt, bei einer Eingabe von N wird ERR=1 gesetzt. Mit ENDE2 wird das Programm beendet und in AL dieser ERRORLEVEL an das aufrufende Programm - meist das Betriebssystem - bergeben. Im Betriebssystem kann dieser ERRORLEVEL, z.B. in einer BATCH-Datei abgefragt werden.

ENDE2:	BEEP

	MOV  AL,ERR		; AL = Beendigungscode (ERRORLEVEL ERR)
	MOV  AH,4Ch		; Programm beenden
	INT  21h

								Syrovatka
DB	"AUFRUF:",CR,LF
DB	"AUTOASK      w    s    q    n   l ~  h   f M	  b 
  `   \ W
  Z ^  V   T   ^`             0 0
  w  w D  u   q   o   k   g   e   a   ] U  [ W  W   S   O                   
    y D  u   q   o   k   g   e   a   ] U  [ W  W   S   O                          x    v C  v E  v   v   v   v   v   v   v   v   v   v o  v q  v s  v %  v '  v   v  <<    ^   ^   ^   \   ?    ? 3  ?   v   v   v  <                   0  <<                   0  3  e  ^ k  A q  A ~  A   ?   ?   ?   ? 0  ? v  ?  <<                   0  <                   0   

v    y   y   y   y   y 	  y ?	  y K	  y M	  y 
  y 
  y 
  y   y :  y o  y   y   y   y   y   y  <    y -  y P  y   y   y   y   y W
  y Y
  y a
  y 
  y 
  y   y   y $  y /  y 1  y \  y ^  y   y  <    y   y   y &  y 0  y g  y   y   y   y    y *  y [  y u  y w  y B  y D  y V  y   y   y   y  <    y   y   y   y   y   y   y   y   y S  y   y   y   y   y   y   y    y B  y D  y   y  <    y   y   y   y %  y 0  y i  y w  y   y   y   y   y   y   y   y   y   y   y   y U  y  <U  W  y d  y f  y   y   y   y   y   y     y   y   y   y   y   y   y   y   y   y U  y  <	         (       5.21.90 05.21.90_  *************************************************************************

CSEG	ENDS

;**************************************************************************

END	START

;**************************************************************************

                                                                                                                                                                                                             