News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

File manipulation in good 'ole 16-bit DOS 6.22

Started by jejump, January 21, 2022, 01:27:08 PM

Previous topic - Next topic

jejump


Hello all!

I am working on a new 16-bit masm project that, in short, opens a user selected binary file (varying input file sizes), makes slight modifications to it, and saves it as a similarly named output file, but with a different file extension.  I'm reading the input file using DOS int 21h, service AH=3Fh.  I'd like to tell DOS to open up (or reserve) RAM enough to accommodate a maximum size file 65536 bytes in size.  If I do this in the data segment of my code like this:

dseg            segment 'DATA'


Input_File                      db              "88888888.333",0
Bin_File_Handle             dw              0000h
Bin_File_Size                 dw              0000h
Bin_File_Data                db              0FFFFh    DUP(?)

   dseg    ends


This causes overflow warnings in the assembly PLUS makes the .exe file unnecessarily huge.  If I sacrifice about 4096 bytes and make the Bin_File_Data array E000h, I don't get the overflow problems anymore, but the .exe file is still really big.  I know this is NOT the right way to do this, but I'm not sure what the right way is.  Any time I've ever needed to work with files on the machine language level in the past, they've been relatively small files (under 2KB) and I could use a single 16KB segment to handle code, data, stack with room to spare, in most cases.  This is new territory for me and I haven't found any good examples searching the internet.

Hopefully, I've made that all understandable.  Thanks for the help!  :thumbsup:

John



jj2007

Hi John,
I haven't done 16-bit stuff for a while, but can't you create a buffer on the stack? Something like

sub sp, 0FFFFh
mov di, sp   ; your buffer
...
add sp, 0FFFFh

jejump


Oh, that's an interesting approach...  I'll look into that a little closer.  I was thinking there was someway to have DOS "assign" a section of memory, but maybe that's not how it works.  Thanks for the suggestion!

Gunther

John,

I've attached the archive fcopy.zip to this post. There it is shown how to proceed with files under DOS. The archive contains the following files:

  • BFCOPY.BAT: Batch file to assemble the source file.
  • FCOPY.ASM: source file
  • FCOPY.EXE: The running EXE.
  • MYFILE.TXT: Test file opened and copied to a new file.
I used JWASM for DOS, but other assemblers like MASM or TASM should also work. However, the BATCH file must then be modified. MYFILE.TXT is hard coded in the source, but can be easily adapted and does not change the principle.

The FCOPY routine has some interesting aspects:

  • Allows the AX (name conflict) parameter to specify a strategy in case a file with the same name already exists.
  • The routine is designed for network operation and regulates access rights accordingly.
  • FCOPY uses all available free DOS memory to ensure an efficient disk access.
  • Cleans up the procedure properly in case of error. When the destination disk is full, the destination file will be deleted.
If you have any questions, don't hesitate to ask. Best regards to Nashville, TN.

Quote from: jj2007 on January 21, 2022, 01:38:24 PM
I haven't done 16-bit stuff for a while, but can't you create a buffer on the stack? Something like

sub sp, 0FFFFh
mov di, sp   ; your buffer
...
add sp, 0FFFFh
Do you really think this is a good idea? DOS programs usually have 1 or 2 KB stack. This is more than sufficient in most cases.
You have to know the facts before you can distort them.

jj2007

Quote from: Gunther on January 21, 2022, 04:01:55 PM
Quote from: jj2007 on January 21, 2022, 01:38:24 PM
I haven't done 16-bit stuff for a while, but can't you create a buffer on the stack? Something like

sub sp, 0FFFFh
mov di, sp   ; your buffer
...
add sp, 0FFFFh
Do you really think this is a good idea? DOS programs usually have 1 or 2 KB stack. This is more than sufficient in most cases.

.nolist
.Model small
.stack 65536
.386

_japheth

Quote from: jj2007 on January 21, 2022, 08:52:10 PM
Quote from: Gunther on January 21, 2022, 04:01:55 PM
Quote from: jj2007 on January 21, 2022, 01:38:24 PM
I haven't done 16-bit stuff for a while, but can't you create a buffer on the stack? Something like

sub sp, 0FFFFh
mov di, sp   ; your buffer
...
add sp, 0FFFFh
Do you really think this is a good idea? DOS programs usually have 1 or 2 KB stack. This is more than sufficient in most cases.

.nolist
.Model small
.stack 65536
.386


IIRC ( :biggrin:) register SP is 16 bit, so ".stack 65536" might actually be a synonyme for ".stack 0"; but I hope the assembler will detect this condition and emit a warning?
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

jejump


Thanks, Gunther, and everyone else helping.  I'm going to download FCOPY right now and scan through it and see what it reveals.

Jj

jj2007

Quote from: _japheth on January 21, 2022, 10:30:44 PMIIRC ( :biggrin:) register SP is 16 bit, so ".stack 65536" might actually be a synonyme for ".stack 0"; but I hope the assembler will detect this condition and emit a warning?

You are perfectly right, but 1. no warning and 2. this works without problems, so I assume the assembler (UAsm64) handles the problem somehow:
  sub sp, 60000
  mov di, sp
  mov al, "x"
  mov cx, 60000
  rep stosb
  add sp, 60000


I don't have a 16-bit debugger on this machine, unfortunately. I am curious, too, why this works:
  tolerance=500 ; 500 is ok, 400 is not
  sub sp, 65536-tolerance
  mov di, sp
  mov cx, (65536-tolerance)/68
  .Repeat
mov si, Chr$("This 67-byte string was copied to the buffer created on the stack", 13, 10)
.Repeat
lodsb
stosb
.Until !al
dec di
dec cx
  .Until Sign?
  mov al, "$"
  stosb
  mov dx, sp
  mov ah, 9 ; the traditional DOS way,
  int 21h ; ending with the $ delimiter
  add sp, 65536-tolerance

_japheth

Quote from: jj2007 on January 21, 2022, 10:47:52 PM
You are perfectly right, but 1. no warning and 2. this works without problems, so I assume the assembler (UAsm64) handles the problem somehow:

I guess the assembler doesn't care. Neither does the MS 16-bit linker - but old Borland's tlink emits an error "invalid stack offset".
It "works" nevertheless, because the DOS memory "management" is somewhat "forgiving" - on most cases it allows a program to run with an initial value of 0000 for SP.
Dummheit, gepaart mit Dreistigkeit - eine furchtbare Macht.

jj2007

UAsm chokes if I put 1 byte more, i.e. 65537, so the assembler is aware of the problem. And the demo works fine, which it wouldn't if no extra stack was allocated. So apparently .stack 65536 does indeed allocate a 64k stack.

Btw I use the MS-DOS Player for Win32-x64 for running my 16-bit executables (msdos\binary\i486_x64\msdos.exe); no idea whether "real" DOS makes any difference :cool:

FORTRANS

Hi,

   How do you have the segment registers set up?  LODS defaults
to using DS.  (It can be overridden with a segment prefix.}  STOS
must use ES.

Regards,

Steve N.

jj2007

Hi Steve,
See the Init macro in DosBasic.inc:
  push @DATA ; set the DS register to DGROUP
  pop ds ; for ds:si (lods)
  push ds
  pop es ; for es:di (scas, stos)

Gunther

Quote from: jj2007 on January 22, 2022, 01:43:29 AM
Btw I use the MS-DOS Player for Win32-x64 for running my 16-bit executables (msdos\binary\i486_x64\msdos.exe); no idea whether "real" DOS makes any difference :cool:

Your application simply crashes in DOSBox 0.74-3. And by the way: The naming convention for DOS is 8.3. Moreover, UASM is not exactly the classic DOS assembler.

But apart from that. The EXE cannot be re-assembled in the form you have attached it. DosBasic.inc is included via the masm32 path. After correcting that, JWASM says:

DosBasic.inc(2) : Warning A4095: Multiple .MODEL directives, .MODEL ignored
DosBasic.inc(2): Included by
  stack16.asm(1): Main line code

TLINK brings the following errors:

Turbo Link  Version 7.00 Copyright (c) 1987, 1994 Borland International
Error: Group DGROUP exceeds 64K
Error: Invalid initial stack offset

The MAP file looks like this:

Error: Group DGROUP exceeds 64K
Error: Invalid initial stack offset

Start  Stop   Length Name               Class

00000H 00000H 00000H STACK16_TEXT       CODE
00000H 0025FH 00260H _TEXT              CODE
00260H 00413H 001B4H _DATA              DATA
00414H 0EF7BH 0EB68H _BSS               BSS
0EF7CH 0EF7CH 00000H CONST              CONST
0EF80H 1EF7FH 10000H STACK              STACK

Since you don't have a 16-bit debugger, I've remedied that. I have attached the archive debug.zip to this post. It contains the very good debugger debug.com maintained by Japheth and a
quick and dirty tutorial for it by Michael Webster.

Finally, as a reminder: Your original proposal was
Quote from: jj2007 on January 21, 2022, 01:38:24 PM
sub sp, 0FFFFh
mov di, sp   ; your buffer
...
add sp, 0FFFFh
You have to know the facts before you can distort them.

TimoVJL

msdos.exe + cv.exe might work for debugging :thumbsup:
td.exe had problems.

Under vDOSPlus td.exe works.

http://www.vdosplus.org/
https://sourceforge.net/projects/vdosplus/


May the source be with you

Gunther

You have to know the facts before you can distort them.