The MASM Forum

Miscellaneous => 16 bit DOS Programming => Topic started by: Pokerice on May 28, 2014, 03:03:38 PM

Title: search and print
Post by: Pokerice on May 28, 2014, 03:03:38 PM
Hi, I am trying to make a simple 16 bit .COM program which basically tries to see if a file exists or not. But it either freezes my command prompt or tells me it encountered some illegal instructions (double clicking the .com file).
Here is my code:

.model tiny

.code

ORG 100H

Start:
        mov ah, 4EH                          ;prepares search first function
        mov dx, offset STRING_LC     ;offset
        mov cx, 0                               ;read only
        int 21
        JC NoFile

File:
        mov ah, 9
        mov dx, offset msg
        int 21
        jc Done
       
NoFile:
        mov ah, 9
        mov dx, offset msg2
        int 21

Done:   
        mov ah, 9
        mov dx, offset msg3
        int 21
     

STRING_LC DB    '*.txt',0        ;file/files looking for

msg3 db 'finish$'
msg db  'file found$'
msg2 db 'file not found$'

END Start
Title: Re: search and print
Post by: sinsi on May 28, 2014, 03:54:34 PM
Code: [Select]
int 21try int 21h

Also
Code: [Select]
jc Donetry jmp Done
Title: Re: search and print
Post by: Pokerice on May 28, 2014, 04:23:56 PM
thank you!!! Silly mistake using jc instead of jmp and I guess you can't leave out the hex :biggrin:
Title: Re: search and print
Post by: Gunther on May 28, 2014, 05:12:44 PM
Hi Pokerice,

Apart from the errors, I can't see the part for going back to DOS. Something like:
Code: [Select]
         mov        ax, 4c00h
         int        21h


Gunther
Title: Re: search and print
Post by: sinsi on May 28, 2014, 05:26:19 PM
Hi Pokerice,

Apart from the errors, I can't see the part for going back to DOS. Something like:
Code: [Select]
         mov        ax, 4c00h
         int        21h


Gunther
Ha! Well spotted. My excuse? Beer goggles...
Title: Re: search and print
Post by: Gunther on May 28, 2014, 06:52:46 PM
Hi sinsi,

beer would be nice. :lol:

Gunther
Title: Re: search and print
Post by: Pokerice on May 28, 2014, 07:03:55 PM
haha thanks gunther 8) 

By the way, using ret is the same right?
Title: Re: search and print
Post by: sinsi on May 28, 2014, 07:17:54 PM
As long as the stack is balanced then RET will work, but only for a .com file.
From memory, the top of the stack is 0, so it RETs to CS:0000, which is an INT 20H.

Better to use the approved way as Gunther has.
Title: Re: search and print
Post by: dedndave on May 28, 2014, 09:17:29 PM
i think the JC might be ok
but, there is a FindFirst function, and a FindNext function
i haven't used it for years - lol

RET is ok for a .COM, exactly as Sinsi mentioned
for .EXE's, they used to...
Code: [Select]
main    PROC    FAR

    xor     ax,ax   ;zero AX
    push    ds      ;initially, the DS register holds the PSP segment
    push    ax

;main code

    ret

main    ENDP

        END     main
because "main" is typed as FAR, the RET at the end will be a RETF
so, it branches to PSP:0

main should be typed as NEAR for a .COM program

INT 21h, AH=4Ch is prefered
Title: Re: search and print
Post by: Pokerice on May 28, 2014, 11:45:43 PM
Thanks.. but dedndave, you have completely lost me at the "...typed as FAR, the RET...." part. :lol:
Title: Re: search and print
Post by: Gunther on May 28, 2014, 11:52:51 PM
Pokerice,

Thanks.. but dedndave, you have completely lost me at the "...typed as FAR, the RET...." part. :lol:

Don't be afraid. In your COM file (limited to 64 KB) are all procedures by defintion near (same segment). Change the FAR to NEAR and the assembler generates the appropriate RET machine code.

But you'll do safe if you use INT 21h with AX = 4c00h. That works for COM and EXE files and - not to forget - for 16-bit Windows applications, too.

Gunther
Title: Re: search and print
Post by: dedndave on May 29, 2014, 03:53:00 AM
here is what i use as a Small model EXE template

Code: [Select]
        .MODEL  Small
        .STACK  4096
        .DOSSEG
        .386
        OPTION  CaseMap:None

;####################################################################################

        .DATA

s$Msg   db 'Hello World !',0Dh,0Ah,24h

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

        .DATA?

;####################################################################################

        .CODE

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

_main   PROC    FAR

        mov     dx,@data
        mov     ds,dx

        mov     dx,offset s$Msg
        mov     ah,9
        int     21h

        mov     ax,4C00h
        int     21h

_main   ENDP

;####################################################################################

        END     _main

here is what i use as a Tiny model COM template

Code: [Select]
        .MODEL  Tiny
        .386
        OPTION  CaseMap:None

;####################################################################################

        .CODE

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

        ORG     100h

_main   PROC    NEAR

        mov     dx,offset s$Msg
        mov     ah,9
        int     21h

        mov     ax,4C00h
        int     21h

_main   ENDP

;####################################################################################

s$Msg   db 'Hello World !',0Dh,0Ah,24h

;####################################################################################

        END     _main

notice that the COM PROC is typed as NEAR
although - it's not needed, as NEAR is the default type
Title: Re: search and print
Post by: FORTRANS on May 29, 2014, 05:21:37 AM
Thanks.. but dedndave, you have completely lost me at the "...typed as FAR, the RET...." part. :lol:

Hi,

   When you jump to, (or call) a routine in the same segment, it is
a NEAR jump, you use only an offset from the current position.
When the code is in a different segment, you need a FAR jump (or
call) specifying both a segment and an offset into that segment.

   In a *.COM program, the PSP, code, data, and stack are all in the
same segment on program load.  A *.EXE program has separate
segments for the PSP and code when the program loads.  It should
(mostly) also have separate segments for the stack and data.

Regards,

Steve N.
Title: Re: search and print
Post by: dedndave on May 29, 2014, 07:30:14 AM
try this one

Code: [Select]
        .MODEL  Tiny
        .386
        OPTION  CaseMap:None

;####################################################################################

        .CODE

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

        ORG     100h

_main   PROC    NEAR

        xor     cx,cx                 ;file attribute = 0
        mov     dx,offset szTxtExt
        mov     ax,4E00h              ;Find First File
        int     21h
        mov     dx,offset s$NotFound
        jc      ShowMessage

        mov     dx,offset s$Found

ShowMessage:
        mov     ah,9
        int     21h

        mov     dx,offset s$Finish
        mov     ah,9
        int     21h

        mov     ax,4C00h
        int     21h

_main   ENDP

;####################################################################################

szTxtExt   db '*.txt',0

s$Found    db 'File Found',13,10,24h
s$NotFound db 'File Not Found',13,10,24h
s$Finish   db 'Finish',13,10,24h

;####################################################################################

        END     _main
Title: Re: search and print
Post by: Pokerice on May 29, 2014, 01:16:36 PM
Thank you all of you 8)! Esepcially FORTRANS for the clear explanation :biggrin:

With that being said, can you use PROC NEAR for some code and PROC FAR for others?
Also, regarding to the segments, do some memory block just get automatically allocated as a certain segment or is it always a specific memory block? Say for DOS, since only one segment,
does it just generate 64kb of memory randomly for your program to use?
Title: Re: search and print
Post by: MichaelW on May 29, 2014, 05:40:36 PM
A segment is not necessarily 64KB. The maximum is 64KB, but a segment could be as small as 16 bytes.

For a .COM program DOS allocates all available memory. For an .EXE program DOS allocates enough memory to contain the program image and the PSP, plus any additional memory specified in the EXE header.
Title: Re: search and print
Post by: Gunther on May 29, 2014, 08:16:33 PM
For a .COM program DOS allocates all available memory. For an .EXE program DOS allocates enough memory to contain the program image and the PSP, plus any additional memory specified in the EXE header.

Right, but EXE programs are often very memory hungry, too. So it's necessary to shrink the memory for the EXE if you need a dynamic buffer during run time.

Gunther 
Title: Re: search and print
Post by: dedndave on May 29, 2014, 08:46:30 PM
for most procedures that you write, you will not use far calls
if you type a procedure as far, the assembler will use a far call automatically
one place you may see far procedures is if you decide to revector an interrupt
another is if you write a device driver
in your own code, you might use far code segments in a Medium or Large memory model program

http://en.wikipedia.org/wiki/Intel_Memory_Model (http://en.wikipedia.org/wiki/Intel_Memory_Model)

in a Small or Compact model program, all code is in the same segment
so, procedures can generally be near

it's hard to write a program that needs more than 64 Kb of code - lol
not to say it hasn't been done
but, you won't do it in a few days   :biggrin:
you are more likely to use multiple data segments
Title: Re: search and print
Post by: FORTRANS on May 29, 2014, 10:36:05 PM
Hi,

With that being said, can you use PROC NEAR for some code and PROC FAR for others?

   Yes, but as Dave said, it is not often that you would want to.
Maybe if you wrote a subroutine library or some such.

Quote
Also, regarding to the segments, do some memory block just get automatically allocated as a certain segment or is it always a specific memory block? Say for DOS, since only one segment,
does it just generate 64kb of memory randomly for your program to use?

   Usually DOS will load your program in the first available memory.
If you have more than one segment in your program, you can
specify the load order, but they will normally be loaded one after
another with no wasted space.  (Give or take.)

For a .COM program DOS allocates all available memory. For an .EXE program DOS allocates enough memory to contain the program image and the PSP, plus any additional memory specified in the EXE header.

   The default for either a *.COM or *.EXE program is to allocate
all memory to the program.  There are LINK options to limit memory
to a lesser value (and programs to edit the EXE header to do the
same thing), but I have seen very few programs that actually do
that.

Right, but EXE programs are often very memory hungry, too. So it's necessary to shrink
the memory for the EXE if you need a dynamic buffer during run time.

   I wrote a program using a variable sized buffer that just uses
the memory following the program without deallocating/reallocating
the memory.  I just set a segment register to the end of the program,
and incremented it for each additional data item.  Use information
from the PSP to locate the end of the memory allocated to the
program.  (And have a whole bunch of fun when your {my} math
does not add up.)  I think the shrink/allocate paradigm is a hold-over
from C programming.  Or it could be that I am just lazy.

you are more likely to use multiple data segments

   Yeah.  Up to a few thousand 48 byte "fake" segments in the
above mentioned program.  I have also written programs that
had data arrays that exceeded the normal segment limits and
thus required more than one data segment.

Regards,

Steve N.
Title: Re: search and print
Post by: Gunther on May 29, 2014, 11:03:20 PM
Steve,

I think the shrink/allocate paradigm is a hold-over
from C programming.  Or it could be that I am just lazy.

in other words, mostly for blended code EXEs (C, Pascal, BASIC + assembly language).

Gunther
Title: Re: search and print
Post by: dedndave on May 29, 2014, 11:11:14 PM
compiled code might well set up the EXE header so it doesn't allocate everything

DOS was relatively easy to play with
you can open debug and dump the memory, starting at the 0:0, if desired

as you dump, you can see...
the interrupt vector table
the BIOS data area
resident DOS (msdos.sys, io.sys, resident part of command.com)
your device drivers (link listed)
and, finally, the PSP for debug

each block of memory is prefaced with a heap allocation block
it's a 16-byte (paragraph) of info linking to the next heap block
as you play with the memory free/allocate functions, you can see the heap allocation blocks change
Title: Re: search and print
Post by: dedndave on May 29, 2014, 11:19:20 PM
in the BIOS data area, there is a variable that tells how much memory is available
when a TSR installs itself high in memory, it might calculate a new top of memory segment and update the variable
so, you can see that up high, too
if you wanted to free and allocate memory - good idea to consult this variable, first   :P
Title: Re: search and print
Post by: Pokerice on May 29, 2014, 11:56:26 PM
Thank you everyone, it is becoming clearer to me now but one thing still confuses me greatly :icon_redface:. I thought that win32 runs with a flat memory model. The memory models shown in http://en.wikipedia.org/wiki/Intel_Memory_Model (http://en.wikipedia.org/wiki/Intel_Memory_Model) seemed to be segmented. So does that mean I can choose to write my code with either flat memory model or segmented?

I understand that basically flat memory model is just making the memory appear to be one continuous block and segmented is just splitting them into sections and accessing them with register and offset(a way to access more memory). So how come I can write using segmented memory model if win32 uses flat memory model?(while using a virtual machine running windows xp 32bit)  Like the "print and search" code I was writing, that is definitely segmented memory model, right?

Could someone explain it kindly and give some examples as to writing what programs in what OS belongs to which memory model. I am sorry for asking so many questions but there seems to be gaps in my knowledge or something I learnt is incorrect.
Title: Re: search and print
Post by: Gunther on May 30, 2014, 03:13:27 AM
Hi Pokerice,

your questions are not so easy to answer.

Gunther
Title: Re: search and print
Post by: dedndave on May 30, 2014, 04:40:39 AM
yes - that wiki page on segmented memory models applies to 16-bit DOS programs
as Gunther mentioned, the flat model is used for windows
Title: Re: search and print
Post by: MichaelW on May 30, 2014, 09:30:59 AM
The default for either a *.COM or *.EXE program is to allocate
all memory to the program.  There are LINK options to limit memory
to a lesser value (and programs to edit the EXE header to do the
same thing), but I have seen very few programs that actually do
that.

What I recall is that the “default” EXE header values effectively specify all available memory.
Title: Re: search and print
Post by: Pokerice on May 30, 2014, 05:42:06 PM
I think i get the gist of it now. And indeed those examples Gunther provided are more than what I can digest. :lol: Going to avoid them for now. Thanks for the help everyone! :biggrin:
Title: Re: search and print
Post by: Gunther on May 30, 2014, 06:57:57 PM
Hi Pokerice,

And indeed those examples Gunther provided are more than what I can digest. :lol: Going to avoid them for now. Thanks for the help everyone! :biggrin:

I wouldn't say that so strict. If you're willing to go that way, you must simply read and learn a lot of new stuff. You should be familiar with the DOS Interrupts for memory management and with such things like DPMI (DOS Protected Mode Interface). That'll work.

Gunther
Title: Re: search and print
Post by: FORTRANS on May 31, 2014, 03:31:56 AM
Hi,

   Okay, one can display the data in the *.EXE header with EXEMOD.EXE
program that came with (at least) MASM version 5.0.  I looked in
the MASM32\BIN, and didn't find it there.  I now see an EXEHDR.EXE
in MASM 6.0, but did not use it.

   Anyway, I wrote an EXEHDR.EXE that only prints out exMinAlloc,
exMaxAlloc, and exCheckSum values as documented in the MS-DOS
5.0 Programmer's Reference.  Attached with some example output.
Amusingly I tried it on itself, and it has a bad exMinAlloc value.  Good
old Microsoft tools.  The example output also shows that many programs
do not have a valid checksum.

Cheers,

Steve N.