ZHCUAQ1F july 2015 – april 2023
调用函数
.call [ret_reg=] func_name ([argument1, argument2,...])
使用 .call 指令调用函数。或者,您可以指定一个分配了调用结果的寄存器。该寄存器可以是符号寄存器或机器寄存器。.call 指令遵循与 C/C++ 编译器相同的寄存器和函数调用惯例。有关信息,请参阅节 8.3和节 8.4。不支持替代寄存器或函数调用惯例。
您不能调用具有可变数量参数的函数,例如 printf。不执行错误检查以确保传递正确数量和/或类型的参数。您不能通过 .call 指令传递或返回结构。
以下是 .call 指令参数的说明:
ret_reg | (可选)分配了调用结果的符号/机器寄存器。如果未指定,汇编优化器会假定调用会用结果覆盖寄存器 A5 和 A4。 | |
func_name | 要调用的函数的名称,或用于间接调用的符号/机器寄存器的名称。不允许使用寄存器对。被调用函数的标签必须在文件中定义。如果函数的代码不在文件中,则必须使用 .global 或 .ref 指令定义标签(有关详细信息,请参阅 TMS320C6000 汇编语言工具用户指南)。如果您要调用 C/C++ 函数,则必须使用该函数的适当链接名。有关更多信息,请参阅节 7.12。 | |
arguments | (可选)作为参数传递的符号/机器寄存器。参数按此顺序传递,不能是常量、存储器引用或其他表达式。 |
默认情况下,编译器会生成 near 调用,如果 near 调用无法到达其目标,链接器会使用 trampoline。要强制执行 far 调用,必须将函数的地址显式加载到寄存器中,然后发出间接调用。例如:
MVK func,reg
MVKH func,reg
.call reg(op1) ; forcing a far call
如果要使用 * 进行间接访问,则必须遵守 C/C++ 语法规则,并使用以下替代语法:
.call [ret_reg =] (* ireg)([arg1, arg2,...])
例如:
.call (*driver)(op1, op2) ; indirect call
.reg driver
.call driver(op1, op2) ; also an indirect call
以下是使用 .call 语法的其他有效示例。
.call fir(x, h, y) ; void function
.call minimal( ) ; no arguments
.call sum = vecsum(a, b) ; returns an int
.call hi:lo = _atol(string) ; returns a long
由于您可以在可使用符号寄存器的任何位置使用机器寄存器名称,因此您或许可以更改函数调用约定。例如:
.call A6 = compute()
结果似乎在 A6 中返回,而不是在 A4 中返回。这不正确。使用机器寄存器不会覆盖调用约定。从 compute 函数返回在 A4 中返回的结果后,MV 指令会将结果传输到 A6。
下面是一个完整的 .call 示例:
.global _main
.global _puts, _rand, _ltoa
.sect ".const"
string1: .string "The random value returned is ", 0
string2: .string " ", 10, 0 ; '10' == newline
.bss charbuf, 20
.text
_main: .cproc
.reg random_value, bufptr, ran_val_hi:ran_val_lo
.call random_value = _rand() ; get a random value
MVKL string1, bufptr ; load address of string1
MVKH string1, bufptr
.call _puts(bufptr) ; print out string1
MV random_value, ran_val_lo
SHR ran_val_lo, 31, ran_val_hi ; sign extend random value
.call _ltoa(ran_val_hi:ran_val_lo, bufptr) ; convert it to a string
.call _puts(bufptr) ; print out the random value
MVKL string2, bufptr ; load address of string2
MVKH string2, bufptr
.call _puts(bufptr) ; print out a newline
.endproc