首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >最常用的指令

最常用的指令
EN

Stack Overflow用户
提问于 2022-11-18 07:01:19
回答 1查看 60关注 0票数 -2

我不时地读到,在所有的指令中,CPU只有很少的部分被使用,上一次是这里,作者写道:“只有少数几个不同的指令,占执行的所有操作的90%”。

最常用的指令是什么?我最感兴趣的是x86-64和arm64。

EN

回答 1

Stack Overflow用户

发布于 2022-11-18 10:35:07

这将因操作系统、编译器、编译器版本、编程语言以及您所要查看的目标的体系结构扩展而有所不同。这进一步取决于你在什么是和不是“相同”指令之间划清界线。

在arm64上,如果您认为movz w0, 0movz w0, 1是不同的,那么您只需将任何二进制代码块分成4字节块,用十六进制打印并在sort | uniq -c中运行。

如果您认为所有的movz都是相同的指令,那么就会产生一个问题:movz w0movz x0是否相同。如果这是“是”,那么还有其他指令,比如add,它们有不同的形式,其中第三个操作数要么是寄存器,要么是即时的。还有一些东西,比如ldr,在索引前后的模式中引入了附加效应。除此之外,还有像mov这样的伪指令,它们可以被编码为movzmovnorr,这取决于操作数是什么。

但是让我们看一个具体的例子:/bin/bash在macOS 12.6.1上的二进制文件。

__TEXT.__text切片的arm64e部分有118587条指令。如果我们拆解它的全部,并试图用...替换所有直接寄存器,用rN替换所有通用寄存器,用rN替换(w|x)zr(w)sp,用fN替换所有浮点寄存器,使用以下命令:

代码语言:javascript
复制
perl -pe 's/b\.\w{2}/b.cond/g;s/\b(x[0-9]+|sp|xzr)\b/rN/g;s/\bw([0-9]+|sp|zr)/rN/g;s/\b[dq][0-9]+/fN/g;s/-?0x[0-9a-f]+/.../g;s/, -?\d+/, .../g;s/(lsl|lsr|asr|uxtw|sxtw) (\d+|0x[0-9a-f]+)/.../g;s/, \.\.\.\]/]/g'

然后将结果按频率排序如下:

代码语言:javascript
复制
sort | uniq -c | perl -pe 's/^\s+//g' | sort -V

然后在ret指令处选择任意的截止点,我们得到:

代码语言:javascript
复制
265 ret
268 brk ...
269 autibsp
271 eor rN, rN, rN, ...
284 sub rN, rN, rN
299 cset rN, eq
312 cmn rN, ...
322 ldur rN, [rN]
332 add rN, rN, rN, ...
363 csel rN, rN, rN, eq
392 orr rN, rN, ...
432 paciza rN
450 ldr rN, [rN, rN]
476 strb rN, [rN]
507 ldp fN, fN, [rN]
578 sxtw rN, rN
745 and rN, rN, ...
780 tbnz rN, ..., ...
805 tbz rN, ..., ...
866 stp rN, rN, [rN]!
871 add rN, rN, rN
978 ldp rN, rN, [rN], ...
1028 invalid
1141 stp fN, fN, [rN]
1170 retab
1290 pacibsp
1457 sub rN, rN, ...
1520 cbnz rN, ...
1567 cmp rN, rN
1622 ldrb rN, [rN]
1695 adrp rN, ...
2548 ldr rN, ...
3504 stp rN, rN, [rN]
3537 ldp rN, rN, [rN]
3996 adr rN, ...
4644 cmp rN, ...
4664 add rN, rN, ...
4728 cbz rN, ...
4966 b ...
5294 str rN, [rN]
5601 b.cond ...
7451 mov rN, ...
7691 nop
8270 ldr rN, [rN]
10181 bl ...
11585 mov rN, rN

这相当于112015条指令,占总数的94.5%。有几件事在这里很突出:

  • 这是一个"arm64e“二进制,这是苹果的名字,他们的ABI与指针身份验证。在常规的arm64目标上,所有的retab都是ret,而pacibspautibsppaciza则根本不存在。
  • 几乎所有出现的brk都遵循autibsp,这是苹果为了解决FEAT_PAuth体系结构扩展的结构缺陷而被迫进行的编译器更改。其余的事件很可能是源中__builtin_trap()的调用。
  • nop是非常常见的。这是由于PC相对寻址,编译器发出像adrp x0, ...; add x0, x0, ...这样的两三条指令,如果目标地址与指令足够接近,则可以在连接到adr x0, ...; nop的时候对其进行优化。nops是否“运行”,或者它们是否刚刚从指令管道中被删除,这是值得商榷的。
  • invalid是非常常见的。这些是在使用它们的函数之后找到的跳转表。它们是数据,而不是代码,因此永远不会实际运行。
  • 浮点寄存器只显示在两个指令中:stpldp.编译器通常使用浮点寄存器进行memcpy和memset操作,其中一个是因为这些寄存器可以容纳128位,另一个是因为它避免了泄漏通用寄存器,这些寄存器比浮点寄存器更有可能已经被分配,至少在命令行二进制文件(如bash )中是这样。我希望在操作系统内核和嵌入式固件中出现类似的情况,但是在与图形相关的代码或机器学习中,这可能看起来非常不同。
  • 绝大多数cmn指令都会检查-1值。这很可能是C中API设计的结果,而不是体系结构固有的结果。

现在取决于你是否想减少这些指令中的一些。但总的来说,我认为这种模式是明确的:

  • 寄存器移动
  • 即时施工
  • 函数调用
  • 无条件分支
  • 条件分支
  • 寄存器比较
  • 内存负载
  • 存储器存储器

占了绝大部分的指令,这是有意义的,因为有了这些积木,你基本上可以做任何事情。几乎所有其他指令都是对这些指令的某种优化,它们更适合,因此很少发生。其余的指令都是特定于体系结构的,并且公开了您本来无法得到的东西,比如brkmsr,但是这些将会更加罕见。不管你看什么样的架构,情况都很可能是这样。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74485971

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档