• Keine Ergebnisse gefunden

Calling procedures with stack frames

Im Dokument . TUrbo Assembler" (Seite 181-185)

Turbo Assembler supports an extended form of the CALL instruction that lets you directly call procedures that use high-level language interfacing conventions.

Arguments to procedures that use high-level language interfacing conventions are passed on the stack in a stack frame. The caller must push these arguments onto the stack before calling the procedure.

The interfacing convention of the procedure determines the order

arguments should be pushed into the stack frame. For BASIC, FORTRAN, and PASCAL procedures, arguments are pushed onto the stack in the order they are encountered; for C and CPP (C++), the arguments are pushed in the reverse order.

The interfacing convention of a procedure also determines whether the procedure or the caller of the procedure must remove the arguments from the stack once the procedure is called. C and C++ require the caller to clean

See Chapter 7 for further information about using MODEL.

up the stack. In all other languages, the procedure itself must remove the arguments from the stack before returning.

Turbo Assembler handles both the proper argument ordering and stack cleanup for you with the extended CALL instruction. The syntax for calling a procedure with parameters follows;

CALL expression [language] [,argument_list]

expression is the target of the CALL instruction. language specifies the interfacing convention to use for the call. If you don't specify a language, Turbo Assembler uses the default language set by MODEL.

Arguments, if any, follow the language identifier. The syntax of each argument in the argument list is the same as for the extended PUSH and POP instructions. You can separate these arguments with commas; for example,

CALL test PASCAL,ax,es OFFSET buffer,blen

PASCAL, the language in the example, causes Turbo Assembler to push the arguments in the same order that it encounters them. This example call is equivalent to

PUSH ax

PUSH es OFFSET buffer PUSH word PTR blen CALL test

A call to a C procedure requires that the arguments be pushed onto the stack in the reverse order. Turbo Assembler automatically does this so that a call of the form

CALL test C,ax,es OFFSET buffer, word PTR blen results in the following code:

PUSH word PTR blen PUSH es OFFSET buffer PUSH ax

CALL test SUB sp,8

When calling a procedure with arguments, you should always list the arguments in the same order they were listed in the procedure header.

Turbo Assembler reverses them if necessary.

. . Remember to separate arguments with commas and components of arguments with spaces. Turbo Assembler, depending on the interfacing convention, can push arguments in reverse order on the stack, but it won't alter the ordering of argument components.

Calling

procedures that contain RETURNS

Calling

procedures that have been prototyped

Calling method procedures for objects:

CALL..METHOD

If the interfacing convention for the call is NOLANGUAGE, Turbo

Assembler reports an error if any arguments are present. Although you can define arguments to a NOLANGUAGE procedure with the ARG directive, you must explicitly push the arguments when you make a call to a

NOLANGUAGE procedure.

Procedures that define some of their arguments with the RETURNS

keyword must be considered specially. These arguments are used to return values to the caller; therefore, the caller always pops them. There is no special extension to the CALL instruction in Turbo Assembler to help pass those arguments specified in a procedure declaration after the RETURNS directive. You must explicitly PUSH these arguments before the CALL, and POP them afterward.

If you've defined the procedure prior to the call or used PROCDESC to prototype the procedure (see Chapter 10), Turbo Assembler will type check any language and arguments specified in the call and generate a warning if the language, number of parameters, or types of parameters don't match.

For example,

test PROCDESC pascal far :word, :dword, :word call test pascal ax,ds bx,cx

call test c, ax,dx, bx,cx call test pascal, eax, ebx, ecx call test pascal, ax,ds bx

iworks fine iwrong language!

iwrong parameter types!

itoo few parameters!

Since the language of the procedure has been specified, you don't have to include it in the call. If you omit it, however, make sure to include the comma that would normally follow it:

call test,ax,ds bx,cx iworks fine

You can also use procedure types (declared with PROCTYPE) to supply a distance and language, and force type-checking to occur. For example,

footype proctype pascal near :word, :dw~rd, :word call footype ptr[bxl,ax,ds bx,cs ino error!

The CALL instruction is extended to support the calling of object methods.

A call to an object method can generate either a direct call (for static methods) or an indirect call (for virtual methods).

Because you can use an indirect call, the instructions that perform the call can destroy the contents of some registers. Therefore, Turbo Assembler lets you select the proper registers if you're using a virtual method call.

~ Here's the syntax of the CALL..METHOD extension:

See Chapter 8 for further information about how to specify a method as virtual or static. registers, even if you know that the method you're calling is static.

As objects are modified, methods can change from being static to virtual.

Tail recursion for object methods:

JMP .. METHOD

CALL instance-ptr METHOD [object_name:]method_name [USES [segreg:]offsreg]

[language_and_args]

instance-ptr must describe an instance of an object. In MASM mode, it's often impossible to determine the name of the object associated with an instance. Therefore, Turbo Assembler allows the object_name field, so that you can specify the instance's object name.

method_name contains the name of the method to be called for the specified object instance.

If the method is virtual and an indirect call is required, the CALL..METHOD instruction normally calls indirectly through ES:BX (or ES:EBX for USE32 models on the 80386 processor). If you want to use other registers, you can override them with the USES clause. segreg is the optional segment register to use, and offsreg is the offset register to use for the call.

For objects declared with near tables, CALL..METHOD only loads the offset register. Turbo Assembler assumes that the segment register is already set up to the correct value.

The language_and_args field of the CALL..METHOD instruction contains the optional language and argument specifications, which are identical in form to that listed previously under "Calling procedures with stack frames."

Calling method procedures for C++ or Pascal usually requires that the instance of the object be passed as an argument on the stack. See Chapter 18 for further information.

Turbo Assembler provides a JMP .. METHOD instruction that corresponds to the CALL..METHOD instruction. Here's its syntax:

JMP instance-ptr METHOD [object_name:]method_name [USES [segreg:]offsreg]

JMP .. METHOD functions exactly like CALL..METHOD except that

• It generates a JMP instead of a CALL instruction .

• It generates procedure epilog code to clean up the stack before the JMP instruction is genera ted.

The JMP .. METHOD instruction makes it possible to write efficient tail recursion code. It's intended to replace the common situation where a

CALL..METHOD instruction is issued to the current method, followed by a RET instruction.

Im Dokument . TUrbo Assembler" (Seite 181-185)