【发布时间】:2019-10-15 23:41:24
【问题描述】:
我正在尝试将一个结构从 (x86) 汇编器传递给堆栈上的 Ada。我已经能够在 C 中成功地使用这种模式来接受将从程序集传递的大量参数包装在一个结构中,我想知道这是否会在 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 个或更多变量,它就会变得有点繁重。如果您想知道我为什么要这样做,它是一个异常处理程序,处理器会自动将变量传递到堆栈以显示寄存器状态。
我们将不胜感激。
【问题讨论】:
-
只是出于好奇:您指的是ARMv7-M reference manual 的B1.5.6 节中描述的处理器行为吗?您是否尝试在 Ada 中(重新)创建 HardFault 异常处理程序(例如 this one)?
-
我试图实现更接近这里描述的技术:wiki.osdev.org/Interrupt_Service_Routines。您可以在大多数面向 x86 的操作系统中找到类似的实现。