我正在将一些 AArch64/ARM64/Apple Silicon 汇编代码从 Linux 移植到 macOS。
\n此代码使用所有 31 个可用寄存器(堆栈指针不算在内)来避免几乎所有溢出情况;Linux 调用约定允许我使用那么多寄存器。
\n如果迫不得已,我承认溢出一个额外的寄存器(从而将其减少到使用 30 个寄存器)是可行的,因为性能受到的影响最小,但如果限制为 29 个或更少的可用寄存器,性能将受到更大的影响。因此,我真的希望至少有 30 个可用寄存器,最好是 31 个。
\n我刚刚从 Apple 官方文档中了解到,保留了两个额外的寄存器,超出了 Linux 调用约定的要求:
\n\n\n尊重特定 CPU 寄存器的用途
\nARM 标准将某些决策委托给平台设计者。Apple 平台遵循以下选择:
\n\n
\n- 该平台保留寄存器x18。不要\xe2\x80\x99 使用该寄存器。
\n- 帧指针寄存器 (x29) 必须始终寻址有效的帧记录。某些函数 \xe2\x80\x94 例如叶函数或尾部调用 \xe2\x80\x94 可能会选择不在该列表中创建条目。因此,即使没有调试信息,堆栈跟踪也始终是有意义的。
\n
尽管有这些说法,我的代码在没有它的情况下似乎运行良好。
\n现在,我完全明白忽略此类 ABI 要求是一件非常糟糕的事情 (TM)。但是,我想确切地了解代码如何因使用 x18 和 x29 而中断。
\n例如,通过阅读上述文档,我的理解是 x29 是为了支持调试或故障转储。假设我不关心调试这个函数(实际上我不关心),或者任何生成的故障转储是否有意义。那么,使用x29有什么坏处吗?
\n至于x18,知道它有什么用吗?我假设(零支持证据)如果在该代码运行时执行中断或上下文切换,则不会保存 x18,因此一旦返回就会破坏我的函数的结果。这将是一个更严重的情况,我会听取建议,在这种情况下不要使用 x18。
\n另请注意,所讨论的代码是叶函数,因此破坏从其中调用的任何函数都没有问题。
\n我是Android开发的新手.我想拨打一个号码,但我不想将号码存储在我的通话记录中.如何在通话结束后从通话记录中删除号码?
我想知道如何将参数传递给C中的函数.存储的值在哪里以及如何检索它们?可变参数传递如何工作?此外,因为它是相关的:返回值怎么样?
我对CPU寄存器和汇编器有基本的了解,但还不足以让我彻底了解GCC向我吐出的ASM.一些简单的注释示例将非常感激.
所以我有一个可以安静地或冗长地工作的功能.在安静模式下,它会产生输出.在详细模式下,它还将中间计算保存到列表中,尽管这样做本身需要额外的计算.
在你问之前,是的,这是一个已经确定的优化瓶颈,并且很少需要详细的输出,所以没关系.
所以问题是,有效处理可能会或可能不会返回第二个值的函数的最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) 我正在尝试将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) 我有一个第三方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 …
在Kip Irvine 的《Assembly Language, Seventh Edition for x86 Processors》第 211 页中,它在5.53 The x86 Calling Convention下说,它解决了 Microsoft x64 Calling Convention,
- 调用子程序时,堆栈指针 (
RSP) 必须在 16 字节边界(16 的倍数)上对齐。该CALL指令将 8 字节返回地址压入堆栈,因此调用程序除了已经为影子空间减去 32 之外,还必须从堆栈指针中减去 8 。
它继续显示一些sub rsp, 8在 之前带有 的程序集sub rsp, 20h(对于 32 字节的影子空间)。
但这是一个安全的约定吗?Microsoft 堆栈是否保证在指令之前按 16 字节对齐CALL?或者,这本书假设堆栈是错误的
CALLCALLsub rsp, 8;才能恢复到 16 字节对齐吗?在 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) 我正在考虑将为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)