News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

PROBLEM IN EXECUTION

Started by Zest, November 08, 2006, 06:57:37 AM

Previous topic - Next topic

Zest

Hi,
Here is a small program that I coded to execute another program.
http://rapidshare.com/files/2394260/EXEC.rar

The fact is that,It doesn't work properly.
I don't know where in the code is wrong and that's why I need your help.
In fact,my aim is to learn how to code a small program which supports Overlays.
So, as the first step I should learn the way we execute other programs.
Pleasle help me in this case.
Regards,
Zest.


TITLE A PROGRAM TO EXECUTE ANOTHER ONE
PAGE 62,133

stseg SEGMENT STACK

      BYTE 64 DUP (?)

stseg ENDS

dtseg SEGMENT PUBLIC 'DATA'
      PathName   BYTE "C:\v.exe",0
      ParamBlock WORD 0
                 DWORD CmdLine
                 DWORD Dummy,Dummy
                 
      CmdLine    BYTE  4,'v.exe',0dh
      Dummy      BYTE  20 DUP (?)   


dtseg ENDS

cdseg SEGMENT PUBLIC 'CODE'
main  PROC FAR
      ASSUME cs:cdseg,ds:dtseg,ss:stseg,es:dtseg

      mov ax,SEG dtseg
      mov ds,ax
      mov es,ax

      mov ah,4Bh
      mov al,0
      mov dx,SEG PathName
      mov ds,dx
      lea dx,PathName
      mov bx,SEG ParamBlock
      mov es,bx
      lea bx,ParamBlock
      int 21h
     
     
      ;Wait for keypress
      xor ah,ah
      int 16h
     
     
      mov ah,4ch
      int 21h
main  ENDP   
cdseg ENDS
PUBLIC main
END main





sinsi

One of the first things to do in a DOS EXE is to adjust your memory, since DOS usually allocates all available memory to the EXE.
When debugging execute.exe, DOS returns with error 8 (no memory) when it tries to EXEC v.exe.
Light travels faster than sound, that's why some people seem bright until you hear them.

eek

If I have a problem like this I try to fix it in tiny steps.

I would make a tiny program to enable another tiny program, like printing a single letter or pixel.

...then spend the next 3 days trying to figure out wtf is going on. :bg

sinsi

Quote from: eek on November 08, 2006, 12:58:49 PM
If I have a problem like this I try to fix it in tiny steps.

I would make a tiny program to enable another tiny program, like printing a single letter or pixel.

...then spend the next 3 days trying to figure out wtf is going on. :bg

Your best friend (really) is DEBUG.EXE and the commands T and P  :bg
Light travels faster than sound, that's why some people seem bright until you hear them.

Zest

Quote from: sinsi on November 08, 2006, 07:38:01 AM
One of the first things to do in a DOS EXE is to adjust your memory, since DOS usually allocates all available memory to the EXE.
When debugging execute.exe, DOS returns with error 8 (no memory) when it tries to EXEC v.exe.

Thanks for the reply.
But could you please let me know the way I can allocate memory for my propgram?
Please explain the process.

Best Regards,
Zest.

japheth


> But could you please let me know the way I can allocate memory for my propgram?

as stated by sinsi, you have to free some DOS memory used by your program *before* you call int 21h, ah=4Bh. This is usually done by calling int 21h, ah=4Ah and register BX set to the amount of paragraphs your program needs to run.

How to calculate this amount?

ES:0000 is the start of the memory block you are using, and SS:SP points to the end of it.

Now you have to calculate the difference and transform it to paragraphs. I guess you can do this task on your own :).



sinsi

Quote from: japheth on November 09, 2006, 11:18:00 AM
ES:0000 is the start of the memory block you are using, and SS:SP points to the end of it.

By the looks of the segment layout, the last segment is actually cdseg not the stack. I would either make stseg the last segment, or
use .model and .dosseg - this way you can use .startup and .exit which will make it a lot easier. Also, 64 bytes is a little small for a stack, even
in DOS - I usually use a 4k stack, since things like XMS require at least 1k of your stack for their use.
Light travels faster than sound, that's why some people seem bright until you hear them.

Zest

Hi,
Thanks for your hints and explanations.
According to what you friends said I did the following.
Let me know if I still have mistakes in this program.

1- I changed the stak segment to this shape.


.DOSSEG

stseg SEGMENT PARA STACK

      BYTE 4096 DUP (?)

stseg ENDS


2-The I Computed the size of running program by following istructions.

     

      mov bx,es ;Copy the first address memory into bx
                 
     
      mov ax,ss
      add ax,sp   ;Computing the size of this running program in paragraphs
      sub ax,bx
      xor cx,cx
      mov cx,16
      cwd
      div cx
      mov bx,ax   ;Release unused memory
      mov ah,4Ah
      int 21h


In fact,"Int 21h with option 4Ah" asks me to direct Es into SEGMENT ADDRESS OF BLOCK.
I don't know this address and thus ignored it.
Let me know where it should point to.

Another question is that why we should use "Int 21h with option 4Ah" ?
I noticed that you want to resize the alocated memory and this action causes the memory to be deallocated and deallocation means having free memory.
The querstion is that why you don't use "int 21h with option 49h" which is specially designed to free up allocated memory.

Is there any way to use this interrupt?


3-This last question is about .DOSSEG Directive.
Here is what I found on NEt about this directive.

Quote.DOSSEG/DOSSEG

Orders the segments according to the DOS segment convention: CODE first, then segments not in DGROUP, and then segments in DGROUP. The segments in DGROUP follow this order:

1.Segments not in BSS or STACK
2.BSS segments
3.STACK segments

So it simply put the stack segment the last segment of your program.
But what I don't know is  BSS segments.
What are BSS segments?

Could you please shed some light?

Thanks in advance.
Best Regards,
Zest.

japheth


Hi,

the code to calc the size of running program has a bug:

1.

      mov bx,es
      mov ax,ss
;;      add ax,sp    ;<- this cannot be added yet
      sub ax,bx

     mov cx,sp     ;convert SP to paragraph "units"
     shr cx,4
     inc cx
     add ax,cx      ;<- and then add here

;      xor cx,cx     ;these 4 lines are not needed
;      mov cx,16   ;since ax already contains paragraphs
;      cwd
;      div cx


> In fact,"Int 21h with option 4Ah" asks me to direct Es into SEGMENT ADDRESS OF BLOCK.
> I don't know this address and thus ignored it.

ES happens to contain that address already. So it is ok to ignore it in this case.

> Is there any way to use this interrupt?

No, int 21h, ah=4Ah must be used, since your program resides in one large memory block whose size has to be reduced, but the block itself cannot be freed.



Zest

Hi,
Thanks for your help.
But I have some questions regarding your algo.
First, you didn't use DIV instruction.
Why did you use SHR instruction?
Does it make any difference?

Second,you just calculated the Paragraph size for the stack,so what about the difference we have between  "ss - es =  "  ?

I mean by subtracting ss from es you will have a number which is the difference between two different segments.
What about this number?
Shouldn't we divide it by 16 to get how many paragraph units are between them?

Third,why did you add one to the result?
I mean what's the role of INCREMENT instruction in your algo?

Maybe,this is because SHR rounds down the result and you increment one to it, to round up the result,like what division instruction do.

I really don't know the fact and I just guess, which might cause you laugh.
:red

Thanks in advance.
Best Regards,
Zest.








japheth


Hi,

> First, you didn't use DIV instruction.
> Why did you use SHR instruction?
> Does it make any difference?

Yes, it is 0,2 ns faster. For an assembly coder, every nanosecond counts.

> Shouldn't we divide it by 16 to get how many paragraph units are between them?

no, since the segment registers already contain paragraph-related addresses.

> Maybe,this is because SHR rounds down the result

Yes. However, this might waste 16 bytes precious DOS memory if the lower 4 bits were already zero. If the launched program needs these 16 bytes desperately, you will have to adjust the algorithm.

Regards

Japheth

Zest

Hi,
Thanks for clarifying the obscure cases.
I still have a few minor questions.

1-I understood the fact about segment registers.
I think this is because we declared them in the program this type:

stseg SEGMENT STACK

      BYTE 64 DUP (?)

stseg ENDS


In this case the default type is PARA .

But what if they are declared this type:


stseg SEGMENT PAGE STACK

      BYTE 64 DUP (?)

stseg ENDS


Shall I write an algo to change the PAGE to byte and then Byte to Paragraph?

2-I think that here, we are calculating logical memory addresses.
Am I right?
Does calculating physical memory addresses make difference in our results?
By saying "calculating physical memory addresses " ,I mean shifting segment addresses 4 bits left and then adding them to instruction counter of that segment.
Here it's SP.

I just want to know if by doing so we will get any better or more precise result in performance.

Thanks.
Best Regards,
Zest.





sinsi

As far as alignment goes (PARA/PAGE) this decides where the segment starts -
  PARA will start on a 16-byte boundary
  PAGE will start on a 256-byte boundary
so the assembler will insert nulls in the preceding segment to align the segment. In theory, you could waste 255 bytes by using PARA e.g.
  dtseg SEGMENT
    var1 BYTE 1
  dtseg ENDS
  stseg SEGMENT PAGE
    BYTE 64 dup (?)
  stseg ENDS

say dtseg is at address 1000:0000 then stseg will be at 1010:0000 (which is also 1000:0100, just to confuse us all) because the assembler
pads dtseg with 255 bytes of crap to make it to the next page (100h bytes, 10h paragraphs). I reckon stick to the default PARA in 16-bit DOS.

With physical/logical addressing, 16-bit real mode uses segmented addressing (segment:offset) to get a 20-bit physical address -
  ssss    ;eg F123
   oooo   ;eg  01A9
  ppppp   ;eg F13D9

and just to finish on a confusing note, a 20-bit address can be one of 4096 segment:offset addresses...
Light travels faster than sound, that's why some people seem bright until you hear them.

Zest

Hi,
Thanks for explanation.
Ok.
Now I need more help.
I want to make the situation more complicated.

If you look at the first post in this topic,you'll see that I put zero in AL to load and execute the second program.
In fact,in thsi part:


      mov ah,4Bh
      mov al,0
      mov dx,SEG PathName
      mov ds,dx
      lea dx,PathName
      mov bx,SEG ParamBlock
      mov es,bx
      lea bx,ParamBlock
      int 21h


Now,I want to put one in Al and just load the second program.
Then I want to change one byte of the second program.(For example the string which is used in V.EXE to show DOS version) And at last I want to run the second program while it's changed already by the First program.

So what should I do after loading the second program by putting 1 in AL.
How can I access to the elements of the second program.
For example data segment and code segment.
Also let me know how to run the second program after changing some of its parts.
Please explain it well or just show me a snippet of code.
So I can understand this concept in coding.


Thanks in advance.
Best Regards,
Zest.









Zest

Hi,
Is there any problems or ambiguous parts in my previous post?
Please let me know if your need more explanation of what I want to do.

Also please let me know how you make OVR files.
As far as I know OVR files are used as overlay files.
Thanks in advance.
Best Regards,
Zest.