我正在尝试用 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
我找到的资源
Procedure Call Standard for the ARM 64-bit Architecture (AArch64) 的第 5.1.1 节文档解释了过程调用期间每个寄存器的用途。
iOS 专用 deviations .
iOS Assembler Directives .
问题
我已经使用 XCTest 测试了代码,创建了两个随机数,在它们上同时运行 Swift 和 Asm 实现,并验证两者报告的结果相同。代码似乎是正确的。
在 asm 文件中:.align 似乎是为了优化 - 这真的有必要吗?如果是,对齐的正确值是多少?
是否有任何来源可以清楚地解释我的特定函数签名的调用约定是怎样的?
一个。我怎么知道输入实际上是通过 x0 和 x1 传递的?
我怎么知道在 x0 中传递输出是正确的?
我怎么知道破坏 x9-x12 和状态寄存器是安全的?
当我从 C 而不是 Swift 调用函数时,调用函数的方式是否相同?
对于 ARM 文档中的 r8 寄存器描述,“间接结果位置寄存器” 是什么意思?
除了 .globl 之外,我还需要任何其他汇编指令吗?
当我设置断点时,调试器似乎对实际位置感到困惑,显示不正确的行等。我做错了什么吗?
最佳答案
.align 2 指令是程序正确性所必需的。 A64 指令需要在 32 位边界上对齐。lhs和rhs存储在X0和X1中在您链接的 ARM 64 位体系结构 (AArch64) 文档的过程调用标准的第 5.4.2 节(参数传递规则)中给出。由于参数都是指针,因此唯一适用的特定规则是 C.7。我应该说使用内联汇编编写代码的一个优点是您不必担心这些。类似于以下未经测试的 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/
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问
我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新rubygems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我有一个.pfx格式的证书,我需要使用ruby提取公共(public)、私有(private)和CA证书。使用shell我可以这样做:#ExtractPublicKey(askforpassword)opensslpkcs12-infile.pfx-outfile_public.pem-clcerts-nokeys#ExtractCertificateAuthorityKey(askforpassword)opensslpkcs12-infile.pfx-outfile_ca.pem-cacerts-nokeys#ExtractPrivateKey(askforpassword)o