[net.lang.pascal] TURBO PASCAL parameter passing problem summary

wei@princeton.UUCP (P Wei) (12/01/85)

After receiving many help from the net and my own experiment, I have writen
a workable assembly language routine which can successfully get the parameter
passing from TURBO and do some local work depending on what parameter I got.
Following is a summary : (Thank you for all of you who supply me useful info)
>From postnews Tue Nov 19 11:51:21 1985
>Subject: TURBO PASCAL and assembly language link ?  emergent!!
>I want to write a routine in assembly language (IBM-PC running DOS2.0) and
>invoke it in TURBO PASCAL. Can anyone tell me if the following is right as
>soon as possible ?
>In TURBO PASCAL program,
>procedure routine(a, b : integer); external 'comfile.com';
>
>The routine in assembly language :
>code segment
>     assume cs:code
>routine  proc near
>	 push bp
>	 mov bp,sp
>	 mov ax,[bp+4]     ;is this to get b parameter?
>			   ;TURBO PASCAL pushes the parameters from left
>			   ;to right. i.e. first parameter is pushed first.
>			   ;Is this right ?
>;
>;By the way, is it typing error in the TURBO PASCAL reference manual (v.3.0),
>;in the section discussing the internal data format and the external procedure,
>;that says mov ax,[bp-1] will get the string length pushed onto the stack?
>;Should that be mov ax,[bp+4] ?
>
---(1) The code writen is correct according to TURBO tutor. However, in this
       way we cannot have any local variables in the assembly routine.
---(2) both mov ax,[bp-1] on page 222 and 253 in the TURBO reference manual
       are 'typing error'. correct code should be bp+4.
>From postnews Tue Nov 19 13:21:15 1985
>Subject: local variable in assembly routine to be call from TURBO PASCAL
>Is the following peiec going to work?
>code     segment
>	 assume cs:code
>routine  proc near
>	 jmp begin
>variable dw ?
>begin:   .
>	 .
>	 .
>	 mov variable,ax
>	 .
>	 .
>
>My final goal is to set a 'static local variable' (like in C) such that on
>second entry into this routine I can still get the value of variable set last
>time.  From the TURBO reference manual, the local variable is stored in stack
>segment. So I think the above routine is not going to work. Can anyone tell
>me a workable procedure ?
>
---No, this is not gona work! 'variable' is referenced with respect to code
   segment in the assembly routine. However, when this routine is inserted
   into pascal program using external declaration like in the first part above,
   the CS is TURBO's cseg and TURBO doesn't make any change to the code
   corresponding to mov variable,ax. This makes mov ... get into wrong place!
>From postnews Thu Nov 21 13:34:25 1985
>Subject: what might go wrong in these code (TURBO PASCAL)???
>program test;
>var
>  a,b : integer;
>procedure call_int7e(a : integer; var b : integer);
>begin inline($b8/$01/$cd/$7e); end;  {mov ax,01
>				      int 7eh}
>begin
>   a := 0;
>   b := 0;
>   call_int7e(a,b);
>   .
>   .
>   .
>When I call call_int in the main program, I suppose that the TURBO first pushes
>the value of a onto the stack, and then pushes the pointer of b onto the stack,
>finally pushes the return address on top of the stack.
>When the program reaches the inline code in call_int7e, it will transfer
>control to the interrupt routine 7eh with a parameter in ax register.
>When the interrupt routine 7eh is reached, the stack will look like :
>sp----> IP        (low address)
>	CS
>	flags
>	return address
>	offset b
>	segment b
>	value of a     (high address) and SS is the one set by TURBO.
>Can anyone tell me if there is anything wrong ?
>
---This method is gona work in terms of capability of dealing with local variables.
   By 'this method' I mean : put the assembly routine in memory (resident) and
   try to interface it through software interrupt from TURBO.
   However, the parameter above is wrong. See below for the correct one.
>From postnews Thu Nov 21 21:17:05 1985
>Subject: How does the inline() work in TURBO PASCAL ?
>In my previous post, I mistyped inline($b8/$01/$cd/$7e); instead of
>the correct inline($b8/>$01/$cd/$7e); .
>The machine was just stuck still forever (needing reboot) after running
>the program. (interrupt 7eh was installed resident)
>Because in that interrupt routine , I need to get the parameters passed
>by the main program in stack(turbo's). Therefore I want to make sure the
>concept stated in the last posting is right.
>Am I wrong about the inline() statement ? I assume it is a statement informing
>the complier and does nothing on the stack (it doesn't push its "argument" onto
>the stack---i.e. the first code executing at run time is $B8).
>Am I right????
>
The correct parameter stack should be
(low address)
bp-->  [bp]  in the assembly routine
       [IP]  int 7eh return address offset
       [CS]  int 7eh return address segment
       [flags] for interrupt call
       [bp?] extra push in TURBO's procedure
       [sp?] extra push in TURBO's procedure
       [ip]  return address to main program
       [offset of b]
       [segment of b]
       [value of a]

----so the point is those extra 4 bytes in the stack must be included
    in order to get the right parameters passing from main program.
    bp? and sp? are my suspect of what they are. My guess is based on some
    clues getting from 'debug experiment' and some inderect information such as
    stated in the reference manual p.214. If you compare the first 2 inline codes
    on p.214 , you will find that the second one has extra two pop's
    (pop sp and pop bp) which there are no corresponding push's in the first
    one. I think this comes from the extra 7 bytes code added in every
    procedure. ( see BYTE vol.10,no.11 p.226 )