标签: calling-convention

违反 macOS ARM64 调用约定的后果

我正在将一些 AArch64/ARM64/Apple Silicon 汇编代码从 Linux 移植到 macOS。

\n

此代码使用所有 31 个可用寄存器(堆栈指针不算在内)来避免几乎所有溢出情况;Linux 调用约定允许我使用那么多寄存器。

\n

如果迫不得已,我承认溢出一个额外的寄存器(从而将其减少到使用 30 个寄存器)是可行的,因为性能受到的影响最小,但如果限制为 29 个或更少的可用寄存器,性能将受到更大的影响。因此,我真的希望至少有 30 个可用寄存器,最好是 31 个。

\n

我刚刚从 Apple 官方文档中了解到保留了两个额外的寄存器,超出了 Linux 调用约定的要求:

\n
\n

尊重特定 CPU 寄存器的用途

\n

ARM 标准将某些决策委托给平台设计者。Apple 平台遵循以下选择:

\n
    \n
  • 该平台保留寄存器x18。不要\xe2\x80\x99 使用该寄存器。
  • \n
  • 帧指针寄存器 (x29) 必须始终寻址有效的帧记录。某些函数 \xe2\x80\x94 例如叶函数或尾部调用 \xe2\x80\x94 可能会选择不在该列表中创建条目。因此,即使没有调试信息,堆栈跟踪也始终是有意义的。
  • \n
\n
\n

尽管有这些说法,我的代码在没有它的情况下似乎运行良好。

\n

现在,我完全明白忽略此类 ABI 要求是一件非常糟糕的事情 (TM)。但是,我想确切地了解代码如何因使用 x18 和 x29 而中断。

\n

例如,通过阅读上述文档,我的理解是 x29 是为了支持调试或故障转储。假设我不关心调试这个函数(实际上我不关心),或者任何生成的故障转储是否有意义。那么,使用x29有什么坏处吗?

\n

至于x18,知道它有什么用吗?我假设(零支持证据)如果在该代码运行时执行中断或上下文切换,则不会保存 x18,因此一旦返回就会破坏我的函数的结果。这将是一个更严重的情况,我会听取建议,在这种情况下不要使用 x18。

\n

另请注意,所讨论的代码是叶函数,因此破坏从其中调用的任何函数都没有问题。

\n

macos assembly abi calling-convention arm64

12
推荐指数
2
解决办法
1439
查看次数

vararg函数如何找出机器码中的参数数量?

printf这样的可变函数如何找出它们得到的参数数量?

显然,参数的数量不会作为(隐藏)参数传递(请参阅asm示例中的printf调用).

有什么诀窍?

assembly printf variadic abi calling-convention

11
推荐指数
4
解决办法
5285
查看次数

呼叫结束后从呼叫记录中删除呼叫

我是Android开发的新手.我想拨打一个号码,但我不想将号码存储在我的通话记录中.如何在通话结束后从通话记录中删除号码?

android calling-convention

11
推荐指数
2
解决办法
2万
查看次数

论证如何传递?

我想知道如何将参数传递给C中的函数.存储的值在哪里以及如何检索它们?可变参数传递如何工作?此外,因为它是相关的:返回值怎么样?

我对CPU寄存器和汇编器有基本的了解,但还不足以让我彻底了解GCC向我吐出的ASM.一些简单的注释示例将非常感激.

c x86 assembly calling-convention

10
推荐指数
3
解决办法
5067
查看次数

Pythonic方法有效地处理可变数量的返回参数

所以我有一个可以安静地或冗长地工作的功能.在安静模式下,它会产生输出.在详细模式下,它还将中间计算保存到列表中,尽管这样做本身需要额外的计算.

在你问之前,是的,这是一个已经确定的优化瓶颈,并且很少需要详细的输出,所以没关系.

所以问题是,有效处理可能会或可能不会返回第二个值的函数的最pythonic方法是什么?我怀疑pythonic方式会被命名为元组或字典输出,例如

def f(x,verbose=False):
    result = 0
    verbosity = []
    for _ in x:
        foo = # something quick to calculate
        result += foo
        if verbose:
            verbosity += # something slow to calculate based on foo
    return {"result":result, "verbosity":verbosity}
Run Code Online (Sandbox Code Playgroud)

但这需要在不需要时构建一个字典.

一些替代方案是:

# "verbose" changes syntax of return value, yuck!
return result if verbose else (result,verbosity)
Run Code Online (Sandbox Code Playgroud)

或使用可变参数

def f(x,verbosity=None):
    if verbosity:
        assert verbosity==[[]]
    result = 0
    for _ in x:
        foo = # something quick to calculate
        result += foo …
Run Code Online (Sandbox Code Playgroud)

python coding-style return-value calling-convention

10
推荐指数
1
解决办法
243
查看次数

从LLVM调用Win32/64函数的正确方法是什么?

我正在尝试将LLVM IR中的方法调用回C++代码.我正在使用64位Visual C++,或者正如LLVM所描述的那样:

Machine CPU:      skylake
Machine info:     x86_64-pc-windows-msvc
Run Code Online (Sandbox Code Playgroud)

对于整数类型和指针类型,我的代码工作正常.但是,浮点数似乎有点奇怪.

基本上这个电话看起来像这样:

struct SomeStruct 
{
    static void Breakpoint( return; } // used to set a breakpoint
    static void Set(uint8_t* ptr, double foo) { return foo * 2; }
};
Run Code Online (Sandbox Code Playgroud)

和LLVM IR看起来像这样:

define i32 @main(i32, i8**) {
varinit:
  // omitted here: initialize %ptr from i8**. 
  %5 = load i8*, i8** %instance0

  // call to some method. This works - I use it to set a breakpoint
  call void @"Helper::Breakpoint"(i8* %5)

  // this …
Run Code Online (Sandbox Code Playgroud)

llvm calling-convention c++11 llvm-ir

10
推荐指数
1
解决办法
497
查看次数

改变呼叫公约

我有一个第三方C API,需要一个__stdcall回调函数.
我的代码有一个外部提供的 __cdecl回调函数.

我无法将函数指针传递给C-API,因为它们被认为是不同的类型.
绕过类型系统并reinterpret_cast<>自然地使用会导致运行时错误.

下面是一个例子在这里:

// C-API
// the stdcall function pointer type:
typedef CTMuint(__stdcall *CTMwritefn)(const void *aBuf, CTMuint aCount, void *aUserData);

// A function needing the callback: 
CTMEXPORT void __stdcall ctmSaveCustom(CTMcontext aContext, CTMwritefn aWriteFn, void *aUserData, int *newvertexindex);
                                                            ^^^^^^^^^^^^^^^^^^^

//////////////////////////////////////////////////////////////////////////////

// C++
CTMuint __cdecl my_func(const void *aBuf, CTMuint aCount, void *aUserData);

// I want to call here:
ctmSaveCustom(context, my_func, &my_data, nullptr);
//                     ^^^^^^^
Run Code Online (Sandbox Code Playgroud)

有没有办法安全地将一个调用约定的函数转换和/或包装到另一个调用约定中?

我确实通过传递一个调用第二个捕获lambda的casted …

c++ function-pointers cdecl calling-convention stdcall

10
推荐指数
1
解决办法
1268
查看次数

Microsoft Stack 是否始终与 16 字节对齐?

Kip Irvine 的《Assembly Language, Seventh Edition for x86 Processors》第 211 页中,它在5.53 The x86 Calling Convention下说,它解决了 Microsoft x64 Calling Convention,

  1. 调用子程序时,堆栈指针 ( RSP) 必须在 16 字节边界(16 的倍数)上对齐。该CALL指令将 8 字节返回地址压入堆栈,因此调用程序除了已经为影子空间减去 32 之外,还必须从堆栈指针中减去 8 。

它继续显示一些sub rsp, 8在 之前带有 的程序集sub rsp, 20h(对于 32 字节的影子空间)。

但这是一个安全的约定吗?Microsoft 堆栈是否保证在指令之前按 16 字节对齐CALL?或者,这本书假设堆栈是错误的

  1. 对齐到之前的 16 字节CALL
  2. 将 8 字节返回地址压入堆栈CALL
  3. 需要额外的操作sub rsp, 8;才能恢复到 16 字节对齐吗?

windows assembly stack x86-64 calling-convention

10
推荐指数
1
解决办法
2155
查看次数

如何获取对象上的 `&lt; ... &gt;` 语法?

在 Raku 中:当我使用 CALL-ME 方法创建对象时,我想使用< ... >签名语法而不是( '...' )when ...is a Str。在文档中,有一个创建运算符的示例,它是具有特殊语法的普通 Raku sub。这种 sub 自动转换< ... >为 Str。例如,如果我有

use v6.d;
class A {
   has %.x;
   method CALL-ME( Str:D $key ) { say %!x{ $key } }
}

my A $q .= new( :x( <one two three> Z=> 1..* ) );
$q('two');
$q<two>;

Run Code Online (Sandbox Code Playgroud)

但这会产生

2
Type A does not support associative indexing.
  in block <unit> at test.raku line 10
Run Code Online (Sandbox Code Playgroud)

object calling-convention raku

10
推荐指数
1
解决办法
305
查看次数

有人可以解释__declspec(裸体)吗?

我正在考虑将为Windows编写的脚本引擎移植到Linux; 这是Winamp的可视化平台AVS.我不确定目前是否可能.从我可以告诉代码正在采取的C函数的地址nseel_asm_atan,并nseel_asm_atan_end和它们存储,它可以在代码执行期间引用表内.

我看过MS的文档,但我不确定究竟__declspec(naked)是做什么的.什么是文档中提到的prolog和epilog代码?这与Windows调用约定有关吗?这是便携式吗?了解使用类似技术的任何基于Linux的示例?

static double (*__atan)(double) = &atan;
__declspec ( naked ) void nseel_asm_atan(void)
{
  FUNC1_ENTER

  *__nextBlock = __atan(*parm_a);

  FUNC_LEAVE
}
__declspec ( naked ) void nseel_asm_atan_end(void) {}
Run Code Online (Sandbox Code Playgroud)

c linux windows assembly calling-convention

9
推荐指数
2
解决办法
6826
查看次数