Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/101.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
64位iOS(A64)上的汇编程序_Ios_Swift_Assembly_Calling Convention_Arm64 - Fatal编程技术网

64位iOS(A64)上的汇编程序

64位iOS(A64)上的汇编程序,ios,swift,assembly,calling-convention,arm64,Ios,Swift,Assembly,Calling Convention,Arm64,我试图用asm实现替换某些方法。目标是iOS上的arm64(iPhone 5S或更高版本)。我想使用一个专用的汇编程序文件,因为内联汇编程序会带来额外的开销,而且非常简单 互联网上没有太多关于这方面的文档,所以我有点不确定我该怎么做。因此,我将描述将函数移动到ASM所遵循的过程 这个问题的候选函数是256位整数比较函数 UInt256.h @import Foundation; typedef struct { uint64_t value[4]; } UInt256; bool

我试图用asm实现替换某些方法。目标是iOS上的arm64(iPhone 5S或更高版本)。我想使用一个专用的汇编程序文件,因为内联汇编程序会带来额外的开销,而且非常简单

互联网上没有太多关于这方面的文档,所以我有点不确定我该怎么做。因此,我将描述将函数移动到ASM所遵循的过程


这个问题的候选函数是256位整数比较函数

UInt256.h

@import Foundation;

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

bool eq256(const UInt256 *lhs, const UInt256 *rhs);
#import "UInt256.h"
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
.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
桥接头.h

@import Foundation;

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

bool eq256(const UInt256 *lhs, const UInt256 *rhs);
#import "UInt256.h"
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
.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
参考实施(Swift)

@import Foundation;

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

bool eq256(const UInt256 *lhs, const UInt256 *rhs);
#import "UInt256.h"
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
.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
UInt256.s

@import Foundation;

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

bool eq256(const UInt256 *lhs, const UInt256 *rhs);
#import "UInt256.h"
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
.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

我找到的资源

  • 本文件第5.1.1节解释了程序调用期间每个寄存器的用途

  • 特定于iOS

  • iOS


问题

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

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

  • 是否有任何来源清楚地解释了我的特定函数签名的调用约定是如何定义的

    a。我如何知道输入实际上是通过
    x0
    x1
    传递的

    b。我如何知道在
    x0
    中传递输出是正确的

    c。我如何知道敲击
    x9
    -
    x12
    和状态寄存器是安全的

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

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

  • 除了
    .globl
    ,我还需要其他汇编指令吗

  • 当我设置断点时,调试器似乎会混淆它的实际位置,显示错误的行等。我是否做错了什么

  • 程序正确性需要
    .align 2
    指令。A64指令需要在32位边界上对齐
  • 您链接的文档对我来说似乎很清楚,不幸的是,这里不是征求建议的地方。
    • 您可以按照链接的ARM 64位体系结构(AArch64)文档的过程调用标准第5.4.2节(参数传递规则)中给出的说明,确定寄存器
      lhs
      rhs
      存储在
      X0
      X1
      中。由于参数都是指针,因此唯一适用的特定规则是C.7
    • 您可以按照第5.5节(结果返回)中给出的说明确定使用哪个寄存器返回中的值。这只是让您遵循与参数相同的规则。由于函数返回一个整数,因此仅适用规则C.7,因此该值以X0形式返回
    • 更改存储在寄存器X9到X12中的值是安全的,因为它们在第5.1.1节(通用寄存器)给出的表中列为临时寄存器
    • 问题是,在C.中SWIFT是否调用了相同的函数,程序调用标准文档和链接的Apple特定异常文档都是用C和C++定义的。斯威夫特大概遵循同样的惯例,但我不知道苹果是否在任何地方都明确表示了这一点。
  • 第5.5节(结果返回)描述了R8的用途。当返回值太大,无法装入用于返回值的寄存器时,使用它。在这种情况下,调用方为返回值创建一个缓冲区,并将其地址放在R8中。然后,该函数将返回值复制到此寄存器
  • 我认为在示例汇编程序中不需要任何其他内容
  • 你问的问题太多了。你应该单独发布一个更详细的问题来描述你的问题
  • 我应该说,使用内联汇编编写代码的一个优点是,您不必担心这些问题。类似于以下未经测试的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;
    }
    

    好的,也许有点笨拙。

    谢谢你详细的回答