将结构/记录从汇编程序传递给Ada

问题描述 投票:1回答:1

我正在尝试将结构从(x86)汇编器传递到堆栈上的Ada。我已经能够成功地在C语言中使用此模式来接受,以将从程序集传递来的大量参数包装在struct中,我想知道这是否会在Ada中以类似方式工作。

这是一个(人为的,最少的)示例:

当我这样做时,调试被调用者将显示所传递的记录包含未初始化的数据。尽管有export指令,但Ada似乎对C调用约定的解释有所不同。RM包含有关将结构从Ada传递到C的信息,说该信息将自动将记录作为指针类型传递,但是反函数看起来并不正确。如果您接受单个access类型,则将使用堆栈中的第一个值来填充它,就像从cdecl所期望的那样。

(请原谅任何小错误,这不是我的实际代码。)

#####################################################################
#  Caller
#
#  This pushes the values onto the stack and calls the Ada function
#####################################################################
.global __example_function
.type __example_function, @function
__example_function:
    push $1
    push $2
    push $3
    push $4
    call accepts_struct
    ret
----------------------------------------------------------------------------
--  Accepts_Struct
--
--  Purpose:
--    Attempts to accept arguments pass on the stack as a struct.
----------------------------------------------------------------------------
procedure Accepts_Struct (
  Struct : Struct_Passed_On_Stack
)
with Export,
  Convention    => C,
  External_Name => "accepts_struct";

----------------------------------------------------------------------------
--  Ideally the four variables passed on the stack would be accepted as
--  the values of this struct.
----------------------------------------------------------------------------
type Struct_Passed_On_Stack is
   record
      A : Unsigned_32;
      B : Unsigned_32;
      C : Unsigned_32;
      D : Unsigned_32;
   end record
with Convention => C;

另一方面,这很好用:

procedure Accepts_Struct (
  A : Unsigned_32;
  B : Unsigned_32;
  C : Unsigned_32;
  D : Unsigned_32
)
with Export,
  Convention    => C,
  External_Name => "accepts_struct";

在这种最小的情况下,这没什么大不了的,但是如果我要传递16个或更多的变量,它将变得很麻烦。如果您想知道为什么要这样做,它是一个异常处理程序,处理器将处理器自动将变量传递到堆栈上以显示寄存器状态。

这里的任何帮助将不胜感激。

ada gnat ada2012
1个回答
0
投票

记录版本不起作用,因为记录未存储在堆栈中。而是将4个Unsigned_32元素存储在堆栈中。如果您真的想使用记录而不是四个单独的无符号整数值,则可以在对“ accepts_struct”的调用中将这四个值分配给记录的成员。Ada希望堆栈中的第一个条目是一条记录,而不是unsigned_32。Ada LRM第6.4.1节指出:

用于评估parameter_association:实际参数为首先评估。对于访问参数,access_definition为详细说明,它将创建匿名访问类型。对于参数(通过任何方式)通过引用(参见6.2)传递的视图转换实际参数与形式参数的名义子类型之间的关系被评估,形式参数表示转化。为由副本传递的in或in参数(请参见6.2)参数对象已创建,实际参数的值为转换为形式参数的名义子类型并分配正式。

此外,参数的传递模式在6.2节中进行了描述:

6.2形式参数模式

parameter_specification声明in中的mode的形式参数出来,还是出来。静态语义学

参数通过复制或引用传递。当一个参数通过复制传递,形式参数表示与实际参数,以及两者之间的任何信息传递仅在执行子程序之前和之后发生。当一个参数通过引用传递,形式参数表示(一个视图由实际参数表示的对象;读取和更新形式参数直接引用实际参数对象。

A类型是基本类型,或者是A类型的副本类型私有类型的后代,其完整类型是按副本类型。一种按副本类型的参数通过副本传递,除非正式参数是显式别名。

A类型是按引用类型,如果它是以下类型之一的后代以下:

带标签的类型;

任务或受保护的类型;

明确限制的记录类型;

具有副引用类型的子组件的复合类型;

私有类型,其完整类型是按引用类型。

依引用类型的参数按引用传递,任何类型的显式别名参数。每个引用的值类型具有关联的对象。对于带括号的表达式,qualified_expression或type_conversion,此对象是与操作数关联。对于conditional_expression,此对象是与已评估的dependent_expression相关联的一个。

对于其他参数,不确定参数是否为通过副本或引用传递。

似乎您的编译器正在尝试通过引用而不是通过副本传递该结构。在C语言中,所有参数均通过副本传递。

© www.soinside.com 2019 - 2024. All rights reserved.