Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- Watcom Debugger Guide - use the call command to call a routine. the call command options are: http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
Use the Call command to call a routine.  The Call command options are:


     Call [/Far|/Interrupt|/Near]
              <address>
              [([<parm>[,<parm>[...]]])] [/|<printlist>]

This command calls the routine at <address> with parameters.

/Far
    Use a far call instruction.

/Near
    Use a near call instruction.

/Interrupt
    Call the routine as if it were an interrupt handler.

<parm>
    is [/<location>] <expr>

<location>
    is [/|<regset>]

    /
        means to put the parm on the stack.

    /<regset>
        means to put the parm into the named registers.

    <regset> is a register aggregate.
        See Watcom Debugger Expression Handling.

<printlist>
    See the print command for details.

Some examples of the Call command follow:  This command calls the function
foo:


     call foo

This command calls the function bar passing the parameters 1, 2, and 3:


     call bar( 1,2,3 )

This command calls foo putting 1 on the stack, 2 in AX and 3 in CX:BX
printing out the value of AX and DX in decimal and hexadecimal respectively
on return:


     call /near foo( // 1, /ax 2, /[cx bx] 3 ) {%d %x} ax,dx

The Call command only uses very basic symbolic information - it's designed
that way so that it can work even when no symbolic information is available.
 This has a number of implications.  The first is that the debugger pays no
attention to any information on where parameters are stored.  For example,
in 32-bit applications, unless explictly instructed otherwise, the first
parm is placed in EAX, the second in EDX, and so on (as defined by the "set
call" command).  That means that you have to do something like:


     call foo( // &a, // 3 )

to get things on to the stack.  This leads to a second, very important
consideration.

The debugger has no idea of the memory model that the program is compiled in
(recall that the 32-bit compiler does support large memory models and far
pointers, even if we don't supply versions of the libraries for it).  That
means that the debugger has no idea on whether the address of a symbol
should be far or near.  It always assumes far, since that never loses
information.  A far pointer would be truncated to a near pointer when moved
into a 32-bit register like EAX but not so when pushed onto the stack.  In
this case, // &a and // 3 cause 48-bit far pointers to be pushed onto the
stack (they are actually pushed as 64 bits for alignment reasons).  Thus the
pointer to b is in the wrong place for the routine to access it (assuming it
is expecting near pointers) and this will likely cause a task exception.  To
avoid this problem and properly pass arguments to the routine, you need to
do the following:


     call foo( // (void near *)&a, // (void near *)3 )

This forces the debugger to push near pointers onto the stack.

Similar considerations apply for the 16-bit case.

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson