Pascal Parameter passing(参数传递)

Parameter passing
 
Parameters are transferred to procedures and functions via CPU registers or the stack, depending on the routine’s calling convention. For information about calling conventions, see Calling conventions.
Variable ( var) parameters are always passed by reference, as 32-bit pointers that point to the actual storage location.
Value and constant ( const) parameters are passed by value or by reference, depending on the type and size of the parameter:
·     An ordinal parameter is passed as an 8-bit, 16-bit, 32-bit, or 64-bit value, using the same format as a variable of the corresponding type.
·     A real parameter is always passed on the stack. A Single parameter occupies 4 bytes, and a Double, Comp, or Currency parameter occupies 8 bytes. A Real48 occupies 8 bytes, with the Real48 value stored in the lower 6 bytes. An Extended occupies 12 bytes, with the Extended value stored in the lower 10 bytes.
·     A short-string parameter is passed as a 32-bit pointer to a short string.
·     A long-string or dynamic-array parameter is passed as a 32-bit pointer to the dynamic memory block allocated for the long string. The value nil is passed for an empty long string.
·     A pointer, class, class-reference, or procedure-pointer parameter is passed as a 32-bit pointer.
·     A method pointer is passed on the stack as two 32-bit pointers. The instance pointer is pushed before the method pointer so that the method pointer occupies the lowest address.
·     Under the register and pascal conventions, a variant parameter is passed as a 32-bit pointer to a Variant value.
·     Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32-bit values. Larger sets, records, and static arrays are passed as 32-bit pointers to the value. An exception to this rule is that records are always passed directly on the stack under the cdecl, stdcall, and safecall conventions; the size of a record passed this way is rounded upward to the nearest double-word boundary.
·     An open-array parameter is passed as two 32-bit values. The first value is a pointer to the array data, and the second value is one less than the number of elements in the array.
When two parameters are passed on the stack, each parameter occupies a multiple of 4 bytes (a whole number of double words). For an 8-bit or 16-bit parameter, even though the parameter occupies only a byte or a word, it is passed as a double word. The contents of the unused parts of the double word are undefined.
Under the pascal, cdecl, stdcall and safecall conventions, all parameters are passed on the stack. Under the pascal convention, parameters are pushed in the order of their declaration (left-to-right), so that the first parameter ends up at the highest address and the last parameter ends up at the lowest address. Under the cdecl, stdcall, and safecall conventions, parameters are pushed in reverse order of declaration (right-to-left), so that the first parameter ends up at the lowest address and the last parameter ends up at the highest address.
Under the register convention, up to three parameters are passed in CPU registers, and the rest (if any) are passed on the stack. The parameters are passed in order of declaration (as with the pascal convention), and the first three parameters that qualify are passed in the EAX, EDX, and ECX registers, in that order. Real, method-pointer, variant, Int64, and structured types do not qualify as register parameters, but all other parameters do. If more than three parameters qualify as register parameters, the first three are passed in EAX, EDX, and ECX, and the remaining parameters are pushed onto the stack in order of declaration. For example, given the declaration
procedure Test(A: Integer; var B: Char; C: Double; const D: string; E: Pointer);
a call to Test passes A in EAX as a 32-bit integer, B in EDX as a pointer to a Char, and D in ECX as a pointer to a long-string memory block; C and E are pushed onto the stack as two double-words and a 32-bit pointer, in that order.
 
Register saving conventions
Procedures and functions must preserve the EBX, ESI, EDI, and EBP registers, but can modify the EAX, EDX, and ECX registers. When implementing a constructor or destructor in assembler, be sure to preserve the DL register. Procedures and functions are invoked with the assumption that the CPU’s direction flag is cleared (corresponding to a CLD instruction) and must return with the direction flag cleared.
译文
 
参数传递
 
传递到过程和函数的参数,是经过CPU寄存器还是经过栈,取决于例程的调用约定。有关调用约定的信息见 调用约定。
变量参数( var参数)总是通过一个引用被传递,该引用作为一个32位的指针,指向实际存储位置。
值参数和常量参数( const参数)通过值或引用被传递,具体情况由参数的类型和尺寸决定:
·     序数型参数作为8位、16位、32位或64位值传递,其格式与相应类型的变量格式相同。
·     实数参数总是在栈中传递。 Single参数占用4个字节, DoubleCompCurrency参数占用8个字节。 Real48占用8个字节,但它的值存储在低的6个字节中。 Extended占用12个字节,它的值存储在低的10个字节中。
·     短串参数作为32位的指针传递,该指针指向一个短串。
·     长串或动态数组参数作为32位指针传递,该指针指向分配给长串或动态数组的内存块。当长串或动态数组为空是,传递的值为 nil
·     指针、类、类引用或过程指针参数坐位32位的指针传递。
·     方法指针作为32位的指针通过栈传递。实例指针在方法指针被推入栈之前被推入栈,因此方法指针占用最低的地址。
·     在 registerpascal调用约定下,变体参数作为指向变体值的32位指针被传递。
·     1、2或4字节的集合、记录和静态数组作为8位、16位和32位的值被传递。更大的集合、记录和静态数组作为指向值的32位指针被传递。这一规则的例外之处是,在 cdeclstdcall以及 safecall调用约定下,记录总是直接在栈中传递,这时传递的记录的尺寸被向上舍入为双字边界。
·     开放数组参数作为两个32位的值被传递。第一个值是指向数组数据的指针,第二个值是一个比数组元素个数少1的值。
当两个参数通过栈被传递时,每个参数占用4字节的整倍数(整数或双字)。对于8位或16位参数,即使参数仅占用一个字节或一个字,但还是作为一个双字传递。双字中未使用的部分是未定义的。
pascalcdeclstdcall以及 safecall调用约定下,所有参数都在栈中传递。在 pascal约定下,参数按照其声明的顺序(自左到右)被推入栈,因此第一个参数最终在最高的地址而最后一个参数最终在最低的地址。在 cdeclstdcallsafecall约定下,参数按照其声明的相反顺序(即自右到左)被推入栈,因此第一个参数最终在最低的地址而最后一个参数最终在最高的地址。
register约定下,一次最多可以在CPU寄存器中传递三个参数,剩下的(如果有)在栈中传递。参数传递按照其声明的顺序(与 pascal约定相同),并且前三个参数按照相同顺序传递到指定的EAX、EDX和ECX寄存器中。实数、方法指针、变体、 Int64以及结构类型不能限制为寄存器参数,除此之外的其他参数都可以。指定作为寄存器的参数如果多于三个,那么前三个被传递到EDA、EDX和ECX,剩余的参数被推到栈中,都是按照参数声明的顺序。例如,给出如下声明
procedure Test(A: Integer; var B: Char; C: Double; const D: string; E: Pointer);
调用 Test时,参数A作为一个32位的整数被传递到EAX寄存器中,B作为一个 Char类型的字符被传递到EDX寄存器中,D作为指向长串内存块的指针被传递到ECX寄存器中,C和E依次作为两个双字和一个32位指针被推入栈中。
 
寄存器保存预定
过程和函数必须保持EBX、ESI、EDI和EBP寄存器,但可以修改EAX、EDX和ECX寄存器。当在内嵌汇编程序中实现构造器或析构器时,应确认保持DL寄存器。假设过程和函数被调用时,CPU的方向标记是清除的(相应的一个CLD指令),那么必须返回清除的方向标记。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值