18.2 C和汇编语句的接口
这个试验已经显示了编写能够调用C程序或者被C程序调用的汇编语句程序所需要的内容。与这个环境相关的结果总结如下---你的环境肯定在某些方面与它不同。
首先,汇编程序中的名字必须遵循外部标识符的规则。在这个系统中,它必须以一个下划线开始。
其次,汇编程序必须遵循正确的函数调用/返回协议。存在两种情况:从一个汇编语句程序调用一个C程序和C程序调用一个汇编程序。为了从汇编程序调用C程序:
1.如果寄存器d0、d1、a0或a1保存了重要的值,它们必须在调用C程序之前进行保存,因为C程序不会保存它们的值;
2.任何参数的参数必须以参数列表相反的顺序压入到堆栈中;
3.函数必须由一条“跳转子程序”类型的指令调用,它会把返回地址压入到堆栈中;
4.当C函数返回时,汇编程序必须清除堆栈中的任何参数;
5.如果汇编程序希望接受一个返回值,它将保存d0中(如果返回值的类型是double,它的另一半将位于d1中);
6.任何在调用之前进行过保存的寄存器此时可以恢复。
为了编写一个由C程序调用的汇编程序:
1.保存任何希望修改的寄存器(除d0、d1、a0和a1之外);
2.参数值从堆栈中获得,因为调用它的C函数把参数压入在堆栈中。
3.如果函数应该返回一个值,它的值应保存在d0中(在这种情况下,d0不能进行保存和恢复);
4.在函数返回之前,函数必须清除任何它压入到堆栈中的内容。
在汇编程序中创建一个完全C风格的堆栈帧并无必要,你所要做的就是调用一个能够以正确的方式压入参数并当它返回时能够正确地执行清理任务的函数。在一个由C程序调用的汇编程序中,必须访问C函数放置在那里的参数。
在实际编写汇编函数之前,需要知道你机器上的汇编语言相关的信息。一些能够让我们明白必须访问C函数放置在那里的参数。一些能够让我们明白一个现有的汇编程序是如何工作的粗浅知识对于编写新程序是远远不够的。
程序18.4和程序18.5是两个从C程序调用汇编函数以及从汇编程序调用C函数的例子。虽然它们都是特定于这个环境的,但对于说明这方面的情况还是非常有用的。第1个例子是一个汇编语言程序,它返回3个整型参数的和。这个函数并没有费心完成堆栈帧,只是计算参数的和并返回。我们将以下面的方式从一个C函数中调用这个函数。
sum = sum_three_values( 25, 14, -6 );
第2个例子显示了一段汇编语言程序,它需要打印3个值,会调用printf函数来完成这项工作。
|
|对3个整数求和,并返回这个值。
|
.text
.global _sum_three_values
_sum_three_values
movel sp@(4),d0 |Get 1st arg,
addl sp@(8),d0 |add 2nd arg,
addl sp@(12),d0 |Get 1ast arg.
rts |Return.
程序18.4 对3个整数求和的汇编语句程序 sum.s
|
|需要打印3个值,x,y和z。
|
movl z,sp@- |Push args on
movl y,sp@- |stack in reverse
movl x,sp@- |oder: format, x,
movl #format,sp@- |y, and z.
jbsr _printf |Now, call printf
addl #16,sp |Clean up stack
\&...
.data
format:.ascii "x = %d, y = %d, and z = %d"
.byte 012, 0 |Newline and null
.even
x: .long 25
y: .long 45
z: .long 50
程序18.5 调用printf函数的汇编语言程序 printf.s
C和指针 第18章 运行时环境 18.2 C和汇编语言的接口
于 2022-07-17 15:47:24 首次发布