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 200In 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.