oDOSseus hat geschrieben:Ich werde es so machen:Deine Antwort verstehe ich inhaltlich nicht, was wahrscheinlich daran liegt, dass ich mich mit assembler nicht soooo gut auskenne.
mfg
Ok, dann versuche ich es mal etwas näher zu erklären. Leider habe ich von C nur wenig Ahnung und so kann ich das Vorgehen nur anhand eines Assembler-Beispiels zeigen.
Ein Möglichkeit besteht darin einen Datenbereich zu laden. Hierfür müssen ggf. einige Änderungen im Codebereich vorgenommen werden und eine Möglichkeit eingebaut werden um Daten nachzuladen.
Wenn im Codebereich relative Adressangaben vorhanden sind die sich auf bestimmte Stellen im Datenbereich beziehen, dann gehen diese möglicherweise verloren.
Angenommen Im Codebereich befinden sich solche relativen Adressangaben die mit einem Label versehen sind um einen Bezug auf bestimmte Stellen im Datenbereich zu bekommen.
Unser Codebereich:
mov ax, Daten ; Adresse des Datensegments
mov ds, ax
mov si, OFFSET TABELLE1
mov di, OFFSET TABELLE2
Und in unserem Datenbereich(Segment-Anfang) sind bestimmte Bereiche so deklariert:
TABELLE1 DB 8 dup (88h) ; Hier wird ein Bereich von 8 Bytes reserviert
TABELLE2 DB 8 dup (44h) ; und hier auch
...
Wenn man nun das ganze assembliert, dann kommt letzendlcih so etwas dabei heraus:
mov si, 0 ; Die obere relative Adressangabe wird zu einer fixen Adressangabe
mov di, 8 ; hier auch
Datenbereich:
DB 88h, 88h, 88h, 88h, 88h, 88h, 88h, 88h
DB 44h, 44h, 44h, 44h, 44h, 44h, 44h, 44h
Wenn man nun diese Bytes im Datenbereich in eine gesonderte Datei speichert, dann kann man sie zur Laufzeit der Anwendung nachladen.
Durch die fixen Adressangaben im Codebereich erhält man aber trotzdem einen Zeiger auf die beiden Tabellen.
Die erste Tabelle im Datenbereich beginnt bei OFFSET 0 und die zweite TABELLE beginnt bei OFFSET 8.
...
Nun muss der Datenbereich zunächst in eine gesonderte Datei gespeichert werden.
Dafür trennen wir den Datenbereich von unserer Anwendung ab und schreiben ihn in eine neue Quelldatei und fügen dort in den Codebereich nur die Befehle ein, um den Datenbereich in eine gesonderte Datei zu speichern:
Unser Codebereich dafür:
mov ax, Daten
mov ds, ax
mov ah, 3Ch ; Datei erstellen
mov dx, OFFSET FILENAME
mov cx, 0 ; Datei Atribut
int 21h
mov bx, ax ; Datei-Handle
mov ah, 40h ; Datei beschreiben
mov dx, OFFSET TABELLE1
mov cx, Anzahl ; Anzahl Bytes
int 21h
mov ah, 3Eh ; Datei schliessen
int 21h
Unser Datenbereich:
TABELLE1 DB 8 dup (88h) ; Hier wird ein Bereich von 8 Bytes reserviert
TABELLE2 DB 8 dup (44h) ; und hier auch
Anzahl = ($-TABELLE1) ; Länge beider Tabellen ermitteln
FILENAME DB "DATEN.TAB", 0
Code: Alles auswählen
RBIL->inter61b.zip->INTERRUP.F
--------D-213C-------------------------------
INT 21 - DOS 2+ - "CREAT" - CREATE OR TRUNCATE FILE
AH = 3Ch
CX = file attributes (see #01401)
DS:DX -> ASCIZ filename
Return: CF clear if successful
AX = file handle
CF set on error
AX = error code (03h,04h,05h) (see #01680 at AH=59h/BX=0000h)
Notes: if a file with the given name exists, it is truncated to zero length
under the FlashTek X-32 DOS extender, the pointer is in DS:EDX
DR DOS checks the system password or explicitly supplied password at
the end of the filename against the reserved field in the directory
entry before allowing access
SeeAlso: AH=16h,AH=3Dh,AH=5Ah,AH=5Bh,AH=93h,INT 2F/AX=1117h
Bitfields for file attributes:
Bit(s) Description (Table 01401)
0 read-only
1 hidden
2 system
3 volume label (ignored)
4 reserved, must be zero (directory)
5 archive bit
7 if set, file is shareable under Novell NetWare
--------D-2140-------------------------------
INT 21 - DOS 2+ - "WRITE" - WRITE TO FILE OR DEVICE
AH = 40h
BX = file handle
CX = number of bytes to write
DS:DX -> data to write
Return: CF clear if successful
AX = number of bytes actually written
CF set on error
AX = error code (05h,06h) (see #01680 at AH=59h/BX=0000h)
Notes: if CX is zero, no data is written, and the file is truncated or
extended to the current position
data is written beginning at the current file position, and the file
position is updated after a successful write
for FAT32 drives, the file must have been opened with AX=6C00h with
the "extended size" flag in order to expand the file beyond 2GB;
otherwise the write will fail with error code 0005h (access denied)
the usual cause for AX < CX on return is a full disk
BUG: a write of zero bytes will appear to succeed when it actually failed
if the write is extending the file and there is not enough disk
space for the expanded file (DOS 5.0-6.0); one should therefore check
whether the file was in fact extended by seeking to 0 bytes from
the end of the file (INT 21/AX=4202h/CX=0000h/DX=0000h)
under the FlashTek X-32 DOS extender, the pointer is in DS:EDX
SeeAlso: AH=28h,AH=3Fh"DOS",AH=93h,INT 2F/AX=1109h
--------D-213E-------------------------------
INT 21 - DOS 2+ - "CLOSE" - CLOSE FILE
AH = 3Eh
BX = file handle
Return: CF clear if successful
AX destroyed
CF set on error
AX = error code (06h) (see #01680 at AH=59h/BX=0000h)
Notes: if the file was written to, any pending disk writes are performed, the
time and date stamps are set to the current time, and the directory
entry is updated
recent versions of DOS preserve AH because some versions of Multiplan
had a bug which depended on AH being preserved
SeeAlso: AH=10h,AH=3Ch,AH=3Dh,INT 2F/AX=1106h,INT 2F/AX=1227h
Im Sourcecode unserer Anwendung haben wir den Datenbereich nur reserviert aber keine Dekleration mehr für bestimmte Bereiche. Hier müssen wir jetzt dafür im Codebereich die Befehle ergänzen um Daten nachzuladen.
Unser Codebereich:
mov ax, DATEN
mov ds, ax
mov ah, 3Dh ; Datei öffnen
mov dx, OFFSET FILENAME
mov al, 0 ; nur lesen
int 21h
mov bx, ax ; Datei-Handle
mov ah, 3Fh ; Datei lesen
mov dx, 0 ; Anfang des Datenbereichs
mov cx, 16 ; Länge der Datei
int 21h
mov ah, 3Eh ; Datei schliessen
int 21h
Unser Datenbereich:
DB 16 dup (88h) ; Hier wird nun ein Bereich für beide Tabellen reserviert
FILENAME DB "DATEN.TAB", 0
Code: Alles auswählen
RBIL->inter61b.zip->INTERRUP.F
--------D-213D-------------------------------
INT 21 - DOS 2+ - "OPEN" - OPEN EXISTING FILE
AH = 3Dh
AL = access and sharing modes (see #01402)
DS:DX -> ASCIZ filename
CL = attribute mask of files to look for (server call only)
Return: CF clear if successful
AX = file handle
CF set on error
AX = error code (01h,02h,03h,04h,05h,0Ch,56h) (see #01680 at AH=59h)
Notes: file pointer is set to start of file
if SHARE or a network is loaded, the file open may fail if the file
is already open, depending on the combination of sharing modes
(see #01403,#01404)
file handles which are inherited from a parent also inherit sharing
and access restrictions
files may be opened even if given the hidden or system attributes
under the FlashTek X-32 DOS extender, the pointer is in DS:EDX
DR DOS checks the system password or explicitly supplied password at
the end of the filename (following a semicolon) against the reserved
field in the directory entry before allowing access
sharing modes are only effective on local drives if SHARE is loaded
BUG: Novell DOS 7 SHARE v1.00 would refuse file access in the cases in
#01403 marked with [1] (read-only open of a read-only file
which had previously been opened in compatibility mode); this was
fixed in SHARE v1.01 of 09/29/94
SeeAlso: AH=0Fh,AH=3Ch,AX=4301h,AX=5D00h,INT 2F/AX=1116h,INT 2F/AX=1226h
Bitfields for access and sharing modes:
Bit(s) Description (Table 01402)
2-0 access mode
000 read only
001 write only
010 read/write
011 (DOS 5+ internal) passed to redirector on EXEC to allow
case-sensitive filenames
3 reserved (0)
6-4 sharing mode (DOS 3.0+) (see #01403)
000 compatibility mode
001 "DENYALL" prohibit both read and write access by others
010 "DENYWRITE" prohibit write access by others
011 "DENYREAD" prohibit read access by others
100 "DENYNONE" allow full access by others
111 network FCB (only available during server call)
7 inheritance
if set, file is private to current process and will not be inherited
by child processes
SeeAlso: #01782,#01403
(Table 01403)
Values of DOS 2-6.22 file sharing behavior:
| Second and subsequent Opens
First |Compat Deny Deny Deny Deny
Open | All Write Read None
|R W RW R W RW R W RW R W RW R W RW
- - - - -| - - - - - - - - - - - - - - - - -
Compat R |Y Y Y N N N 1 N N N N N 1 N N
W |Y Y Y N N N N N N N N N N N N
RW|Y Y Y N N N N N N N N N N N N
- - - - -|
Deny R |C C C N N N N N N N N N N N N
All W |C C C N N N N N N N N N N N N
RW|C C C N N N N N N N N N N N N
- - - - -|
Deny R |2 C C N N N Y N N N N N Y N N
Write W |C C C N N N N N N Y N N Y N N
RW|C C C N N N N N N N N N Y N N
- - - - -|
Deny R |C C C N N N N Y N N N N N Y N
Read W |C C C N N N N N N N Y N N Y N
RW|C C C N N N N N N N N N N Y N
- - - - -|
Deny R |2 C C N N N Y Y Y N N N Y Y Y
None W |C C C N N N N N N Y Y Y Y Y Y
RW|C C C N N N N N N N N N Y Y Y
Legend: Y = open succeeds, N = open fails with error code 05h
C = open fails, INT 24 generated
1 = open succeeds if file read-only, else fails with error code
2 = open succeeds if file read-only, else fails with INT 24
SeeAlso: #01636,#01404
(Table 01404)
Values for DOS 7.x file sharing behavior:
| Second and subsequent Opens
First |Compat Deny Deny Deny Deny
Open | All Write Read None
|R W RW A R W RW A R W RW A R W RW A R W RW A
- - - - -| - - - - - - - - - - - - - - - - - - - - - - - -
Compat R |Y Y Y Y N N N N Y N N Y N N N Y Y N N Y
W |Y Y Y C N N N N N N N N N N N Y Y N N Y
RW|Y Y Y C N N N N N N N N N N N Y Y N N Y
NA|Y C C Y N N N N Y N N Y N N N Y Y N N Y
- - - - -|
Deny R |C C C C N N N N N N N N N N N N N N N N
All W |C C C C N N N N N N N N N N N N N N N N
RW|C C C C N N N N N N N N N N N N N N N N
NA|C C C C N N N N N N N N N N N N N N N N
- - - - -|
Deny R |Y C C Y N N N N Y N N Y N N N Y Y N N Y
Write W |C C C C N N N N N N N N Y N N Y Y N N Y
RW|C C C C N N N N N N N N N N N Y Y N N Y
NA|Y C C Y N N N N Y N N Y N N N Y Y N N Y
- - - - -|
Deny R |C C C C N N N N N Y N N N N N N N Y N N
Read W |C C C C N N N N N N N N N Y N N N Y N N
RW|C C C C N N N N N N N N N N N N N Y N N
NA|Y Y Y Y N N N N Y Y Y Y N N N Y Y Y Y Y
- - - - -|
Deny R |Y Y Y Y N N N N Y Y Y Y N N N Y Y Y Y Y
None W |C C C C N N N N N N N N Y Y Y Y Y Y Y Y
RW|C C C C N N N N N N N N N N N Y Y Y Y Y
NA|Y Y Y Y N N N N Y Y Y Y N N N Y Y Y Y Y
Legend: R -> reading, W -> writing, RW -> both reading & writing,
A/NA -> reading without access time update
Y = open succeeds, N = open fails with error code 05h
C = open fails, INT 24 generated
SeeAlso: #01403,#01636
--------D-213F-------------------------------
INT 21 - DOS 2+ - "READ" - READ FROM FILE OR DEVICE
AH = 3Fh
BX = file handle
CX = number of bytes to read
DS:DX -> buffer for data
Return: CF clear if successful
AX = number of bytes actually read (0 if at EOF before call)
CF set on error
AX = error code (05h,06h) (see #01680 at AH=59h/BX=0000h)
Notes: data is read beginning at current file position, and the file position
is updated after a successful read
the returned AX may be smaller than the request in CX if a partial
read occurred
if reading from CON, read stops at first CR
under the FlashTek X-32 DOS extender, the pointer is in DS:EDX
BUG: Novell NETX.EXE v3.26 and 3.31 do not set CF if the read fails due to
a record lock (see AH=5Ch), though it does return AX=0005h; this
has been documented by Novell
SeeAlso: AH=27h,AH=40h,AH=93h,INT 2F/AX=1108h,INT 2F/AX=1229h
--------D-213E-------------------------------
INT 21 - DOS 2+ - "CLOSE" - CLOSE FILE
AH = 3Eh
BX = file handle
Return: CF clear if successful
AX destroyed
CF set on error
AX = error code (06h) (see #01680 at AH=59h/BX=0000h)
Notes: if the file was written to, any pending disk writes are performed, the
time and date stamps are set to the current time, and the directory
entry is updated
recent versions of DOS preserve AH because some versions of Multiplan
had a bug which depended on AH being preserved
SeeAlso: AH=10h,AH=3Ch,AH=3Dh,INT 2F/AX=1106h,INT 2F/AX=1227h
Eine weiter Möglichkeit mit ähnlicher Vorgehensweise besteht darin zur Laufzeit unserer Anwendung Speicher von DOS anzufordern, um dort hinein unsere Daten zu laden.
So können wir auf das Reservieren der Tabellen im Datenbereich völlig verzichten, so das unsere Anwendung selber kleiner wird.
So bekommt das Nachladen unserer Daten auch einen Sinn, denn sonst könnte man einfach nur einen Bereich für beide Tabellen zusammen im Datenbereich reservieren,
wobei nur die Adressbezüge zu den Tabellen verloren gehen, wenn man anstelle von relativen Adressangaben mit Label verzichtet und dafür fixe Adressen im Codebereich verwendet die auf die Tabellen zeigen.
(Aber auch das würde unseren Quellcode ja schon kleiner machen.)
Beim Anfordern von Speicher erhalten wir dadurch eine Segmentadresse wohin wir unsere Daten laden können. Das DS-Segmentregister muss dafür vor dem "Datei lesen" auf dieses angeforderte Segment gelegt werden.
Da dieser Beitrag jedoch schon etwas länger ist lasse ich das aber mal weg.
...
Auch die anderen von mir angesprochene Möglichkeiten den Codebereich mit neuen Opcodes aus einer anderen Datei zu überschreiben
und auch die Möglichkeit eine zweite Anwendung aus der Anwendung heraus zu starten (wie es z.B. auch der Norten Commander macht) lasse ich hier mal unberücksichtigt.
Ggf. kann ich das in einem neuen Beitrag genauer aufzeigen.
Dirk