EXTRN WDECIMAL:FAR
CDSEG SEGMENT
ASSUME CS:CDSEG, DS:CDSEG
MAIN PROC
CALL WDECIMAL
MAIN ENDP
NUMBER DB 256 DUP(?)
CDSEG ENDS
SSEG SEGMENT STACK
DW 128 DUP(?)
SSEG ENDS
END MAIN
PUBLIC WDECIMAL
CSEG SEGMENT
ASSUME CS:CSEG
WDECIMAL PROC FAR
WDECIMAL ENDP
CSEG ENDS
END
Program Uebung3;
Uses Crt;
Var Screen : Array[0..24,0..79] Of Integer Absolute $B800:$0000;
I,J : Integer;
Procedure MultiSwap(Count:Integer; Var X,Y:Integer);
Var Z : Integer;
Begin
While Count > 0 Do Begin
Z := X;
X := Y;
Y := Z;
Count := Count-1
End
End;
Begin
For I := 0 To 24 Do
For J := 0 To 79 Do
MultiSwap(I*J,Screen[I,J],Screen[24-I,79-J]);
Repeat Until ReadKey = #13
End.
Dies ist sicher keine "Musterlösung", jedoch eine Lösung, die in der Klausur mit dem Urteil "sehr gut" benotet werden würde :
; Program Uebung3;
STAPEL SEGMENT STACK
DW 256 DUP (?)
STAPEL ENDS
; Uses Crt;
CRT SEGMENT
ASSUME CS:CRT
READKEY PROC FAR
MOV AH,8
INT 21h
RET
READKEY ENDP
CRT ENDS
; Var Screen : Array[0..24,0..79] Of Integer Absolute $B800:$0000;
SCREEN SEGMENT AT 0B800h
DW 2000 DUP (?)
SCREEN ENDS
; I,J : Integer;
DATA SEGMENT
I DW ?
J DW ?
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
; Procedure MultiSwap(Count:Integer; Var X,Y:Integer);
MULTISWAP PROC
COUNT EQU WORD PTR [BP+12]
SEGX EQU [BP+10]
OFFX EQU [BP+8]
SEGY EQU [BP+6]
OFFY EQU [BP+4]
PUSH BP
MOV BP,SP
; Var Z : Integer;
Z EQU [BP-2]
SUB SP,2
; Begin
PUSH DS
PUSH AX
PUSH BX
; While Count > 0 Do Begin
WHILEC: CMP COUNT,0
JLE ENDWHILEC
; Z := X;
MOV DS,SEGX
MOV BX,OFFX
MOV AX,[BX]
MOV Z,AX
; X := Y;
MOV DS,SEGY
MOV BX,OFFY
MOV AX,[BX]
MOV DS,SEGX
MOV BX,OFFX
MOV [BX],AX
; Y := Z;
MOV AX,Z
MOV DS,SEGY
MOV BX,OFFY
MOV [BX],AX
; Count := Count-1
DEC COUNT
; End
JMP WHILEC
ENDWHILEC:
; End;
POP BX
POP AX
POP DS
MOV SP,BP
POP BP
RET 10
MULTISWAP ENDP
; Begin
UEBUNG3 PROC
MOV AX,DATA
MOV DS,AX
MOV AX,SCREEN
MOV ES,AX
MOV I,0
; For I := 0 To 24 Do
FORI: CMP I,24
JG ENDFORI
MOV J,0
; For J := 0 To 79 Do
FORJ: CMP J,79
JG ENDFORJ
; MultiSwap(I*J,Screen[I,J],Screen[24-I,79-J]);
MOV AX,I
MUL J
PUSH AX
PUSH ES
MOV AX,I
MOV DX,160
MUL DX
MOV DX,J
SHL DX,1
ADD AX,DX
PUSH AX
PUSH ES
MOV AX,I
NEG AX
ADD AX,24
MOV DX,160
MUL DX
MOV DX,J
NEG DX
ADD DX,79
SHL DX,1
ADD AX,DX
PUSH AX
CALL MULTISWAP
INC J
JMP FORJ
ENDFORJ:
INC I
JMP FORI
ENDFORI:
; Repeat Until ReadKey = #13
REPEAT: CALL READKEY
CMP AL,13
JNE REPEAT
; End.
MOV AX,4C00h
INT 21h
UEBUNG3 ENDP
CODE ENDS
END UEBUNG3
MOV DL,43h ; Offsetadresse 100
MOV DL,21h
MOV DX,4321h
MOV OPA,DX
MOV DX,OPA
MOV TABL[SI],DX
MOV DX,TABL[SI]
MOV OPA,4321h
MOV TABL[SI],4321h
INT 20h
CALL UP ; Offsetadresse 300
...
UP PROC ; Offsetadresse 400
...
UP ENDP
UP PROC ; Offsetadresse 200
...
UP ENDP
...
CALL UP ; Offsetadresse 300
JE MARKE ; Offsetadresse 200
...
MARKE:... ; Offsetadresse 230
MARKE:... ; Offsetadresse 1D0
...
JE MARKE ; Offsetadresse 200
In allen zugrundeliegenden Assembler-Programmen stehen ab der Offsetadresse 150 jeweils folgende Daten :
OPA DW ? OPB DB ? OPC DW ? TABL DW 10 DUP (?)Hinweis : Alle Offsetadressen sind in hexadezimaler Form angegeben.
Program EasyCode;
Var B : Byte;
C : Char;
F : File Of Byte;
I : Integer;
S : String;
Begin
If ParamCount = 0 Then
Assign(F,'EASYCODE.DTA')
Else
Assign(F,ParamStr(1));
Rewrite(F);
While Not Eof Do Begin
ReadLn(S);
I := 1;
While I<=Length(S) Do Begin
C := S[I];
B := 0;
While (I<=Length(S)) And (S[I]=C) Do Begin
I := I+1;
B := B+1
End;
Write(F,B);
B := Ord(C);
Write(F,B)
End;
B := 0;
Write(F,B)
End;
Close(F)
End.
Program Decode;
Var B1 : Byte;
B2 : Byte;
F : File Of Byte;
Begin
If ParamCount = 0 Then
Assign(F,'EASYCODE.DTA')
Else
Assign(F,ParamStr(1));
{$I-} Reset(F); {$I+}
If Ioresult<>0 Then
WriteLn('DECODE: Quelle existiert nicht !')
Else Begin
While Not Eof(F) Do Begin
Read(F,B2);
If B2=0 Then
WriteLn
Else Begin
B1:=B2;
Read(F,B2);
Repeat
Write(Chr(B2));
B1 := B1-1
Until B1=0
End
End;
Close(F)
End
End.
| INT 21h MS-DOS Funktionsaufruf | |||
|---|---|---|---|
| AH | Wirkung | Eingabe | Ausgabe |
| 3Ch | Logischen Zugriffskanal definieren (create handle) "Datei anlegen und für Schreib-/Lesezugriffe öffnen" | CX = Dateiattribut (0 : keine Attribute) DS:DX = Adresse Dateiname (nullterminiert) | AX = Nummer I/O-Kanal oder Fehlercode bei gesetztem Carry-Flag |
| 3Dh | Logischen Zugriffskanal öffnen (open handle) "Datei für Lese-, Schreib- oder Schreib-/Lesezugriff öffnen" | AL=0 : Lesezugriff AL=1 : Schreibzugriff AL=2 : Schreib-/Lesezugriff DS:DX = Adresse Dateiname (nullterminiert) | AX = Nummer I/O-Kanal oder Fehlercode bei gesetztem Carry-Flag |
| 3Eh | Logischen Zugriffskanal schließen (close handle) "Datei schließen" | BX = Nummer I/O-Kanal | |
| 3Fh | Lesen von Datei bzw. Gerät (read file/device) | BX = Nummer I/O-Kanal (0 : Standard-Eingabe, 1 : Standard-Ausgabe) CX = Anzahl der zu lesenden Zeichen DS:DX = Adresse Eingabepuffer | AX = Anzahl tatsächlich gelesener Zeichen (AX<CX, falls EOF erreicht) oder Fehlercode bei gesetztem Carry-Flag |
| 40h | Schreiben auf Datei bzw. Gerät (write file/device) | BX = Nummer I/O-Kanal (0 : Standard-Eingabe, 1 : Standard-Ausgabe) CX = Anzahl der zu schreibenden Zeichen DS:DX = Adresse Ausgabepuffer | AX = Anzahl tatsächlich geschriebener Zeichen (AX<CX bedeutet Fehler) oder Fehlercode bei gesetztem Carry-Flag |
Weitere Informationen zur Dateiverarbeitung unter MS-DOS :
Program Uebung6;
Const S : String = 'Die letzte Uebungsaufgabe im Sommersemester 2000';
{$L TOOLBOX}
Function IFak(X:Integer):Integer; External;
{ Fakultaetsberechnung iterativ }
Function RFak(X:Integer):Integer; External;
{ Fakultaetsberechnung rekursiv }
Procedure WriteDez(X:Integer); External;
{ Dezimalzahlenausgabe }
Function Count(C:Char; Var S:String):Integer; External;
{ Haeufigkeitsberechnung (von C in S) }
Begin
WriteDez(IFak(5));
WriteDez(RFak(5));
WriteDez(-1*IFak(5));
WriteDez(-1*RFak(5));
WriteDez(Count('e',S))
End.