gpt4 book ai didi

ios - 64 位 iOS (A64) 上的汇编器

转载 作者:搜寻专家 更新时间:2023-10-30 23:10:43 24 4
gpt4 key购买 nike

我正在尝试用 asm 实现替换某些方法。目标是 iOS 上的 arm64(iPhone 5S 或更新版本)。我想使用专用的汇编程序文件,因为内联汇编程序会带来额外的开销,而且相当 cumbersome to use with A64 memory offsets .

Internet 上没有太多关于此的文档,所以我不确定我的做法是否正确。因此,我将描述我将函数移至 ASM 所遵循的过程。


本题候选函数为256位整数比较函数。

UInt256.h

@import Foundation;

typedef struct {
uint64_t value[4];
} UInt256;

bool eq256(const UInt256 *lhs, const UInt256 *rhs);

Bridging-Header.h

#import "UInt256.h"

引用实现(Swift)

let result = x.value.0 == y.value.0
&& x.value.1 == y.value.1
&& x.value.2 == y.value.2
&& x.value.3 == y.value.3

UInt256.s

.globl _eq256
.align 2
_eq256:
ldp x9, x10, [x0]
ldp x11, x12, [x1]
cmp x9, x11
ccmp x10, x12, 0, eq
ldp x9, x10, [x0, 16]
ldp x11, x12, [x1, 16]
ccmp x9, x11, 0, eq
ccmp x10, x12, 0, eq
cset x0, eq
ret

我找到的资源


问题

我已经使用 XCTest 测试了代码,创建了两个随机数,在它们上同时运行 Swift 和 Asm 实现,并验证两者报告的结果相同。代码似乎是正确的。

  1. 在 asm 文件中:.align 似乎是为了优化 - 这真的有必要吗?如果是,对齐的正确值是多少?

  2. 是否有任何来源可以清楚地解释我的特定函数签名的调用约定是怎样的?

    一个。我怎么知道输入实际上是通过 x0x1 传递的?

    我怎么知道在 x0 中传递输出是正确的?

    我怎么知道破坏 x9-x12 和状态寄存器是安全的?

    当我从 C 而不是 Swift 调用函数时,调用函数的方式是否相同?

  3. 对于 ARM 文档中的 r8 寄存器描述,“间接结果位置寄存器” 是什么意思?

  4. 除了 .globl 之外,我还需要任何其他汇编指令吗?

  5. 当我设置断点时,调试器似乎对实际位置感到困惑,显示不正确的行等。我做错了什么吗?

最佳答案

  1. .align 2 指令是程序正确性所必需的。 A64 指令需要在 32 位边界上对齐。
  2. 您链接的文档对我来说似乎很清楚,不幸的是,这不是寻求建议的地方。
    • 您可以按照说明确定寄存器lhsrhs存储在X0X1中在您链接的 ARM 64 位体系结构 (AArch64) 文档的过程调用标准的第 5.4.2 节(参数传递规则)中给出。由于参数都是指针,因此唯一适用的特定规则是 C.7。
    • 您可以按照第 5.5 节(结果返回)中的说明确定使用哪个寄存器返回值。这只是让您遵循与参数相同的规则。由于该函数返回一个整数,仅适用规则 C.7,因此该值在 X0 中返回。
    • 更改存储在寄存器 X9 到 X12 中的值是安全的,因为它们在第 5.1.1 节(通用寄存器)中给出的表中列为临时寄存器
    • 真正的问题是函数在 Swift 中的调用方式是否与在 C 中的调用方式相同。您链接的过程调用标准文档和 Apple 特定异常文档都是根据 C 和 C++ 定义的。大概 Swift 遵循相同的约定,但我不知道 Apple 是否已经在任何地方明确说明了这一点。
  3. R8 的用途在第 5.5 节(结果返回)中有描述。当返回值太大而无法放入用于返回值的寄存器时使用它。在这种情况下,调用者为返回值创建一个缓冲区并将其地址放入 R8 中。然后该函数将返回值复制到该寄存器中。
  4. 我认为您的示例汇编程序中不需要任何其他内容。
  5. 你问的问题太多了。您应该发布一个单独且更详细的问题来描述您的问题。

我应该说使用内联汇编编写代码的一个优点是您不必担心这些。类似于以下未经测试的 C 代码应该不会太笨拙:

bool eq256(const UInt256 *lhs, const UInt256 *rhs) {
const __int128 *lv = (__int128 const *) lhs->value;
const __int128 *rv = (__int128 const *) rhs->value;

uint64_t l1, l2, r1, r2, ret;

asm("ldp %1, %2, %5\n\t"
"ldp %3, %4, %6\n\t"
"cmp %1, %3\n\t"
"ccmp %2, %4, 0, eq\n\t"
"ldp %1, %2, %7\n\t"
"ldp %3, %4, %8\r\n"
"ccmp %1, %3, 0, eq\n\t"
"ccmp %2, %4, 0, eq\n\t"
"cset %0, eq\n\t",
: "=r" (ret), "=r" (l1), "=r" (l2), "=r" (r1), "=r" (r2)
: "Ump" (lv[0]), "Ump" (rv[0]), "Ump" (lv[1]), "Ump" (rv[1])
: "cc")

return ret;
}

好吧,也许它有点笨拙。

关于ios - 64 位 iOS (A64) 上的汇编器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30947422/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com