汇编中的 AT&t 语法?



我在汇编中有多个非常小的问题,这些问题也是相关的,所以我在这个问题中收集了它们,而不是打开多个问题并在论坛上发垃圾邮件。

所有问题都与汇编语言语法有关:

  1. 为什么我不能这样写:

    cmp %eax, $0x2
    jg goHere
    

为什么它不允许做比较操作(结果不保存在一个操作数中,所以不允许它没有意义…)注意:我知道我可以通过颠倒顺序来解决这个问题,并执行jl而不是jg

att语法这是应该检查是否大于0 x2 % eax。

  1. 为什么我可以写:

    mov $41, %rax
    

    当我不能写:

    mov ($41), %rax
    

这很奇怪,有人告诉我在汇编中使用大括号并不重要。

  1. 在内存中保存字符串时,我们写入"ABC"在地址0x100中,内存应该是什么样子的:

    0x100 - A0x101 - B0x102 - C

    0x100 - C0x101 - B0x102 - A

For 1,我对x86的原始设计没有特别的了解,但我怀疑我们没有cmp %reg, $imm的原因是因为cmpsub之间的关系。指令cmp $imm, %reg的行为与sub $imm, %reg完全相同,唯一的例外是cmp的减法结果不会写入目标%reg,而是被丢弃。但是减法的结果仍然由CPU内部计算,并用于设置标志。(至少这在概念上是正确的,早期的cpu几乎肯定会做完整的减法;现代cpu可能有一些我不知道的优化)

所以这意味着一旦你有了sub,cmp几乎可以免费实现。你可以使用几乎完全相同的电路和/或微码。但是你仍然需要解码指令,所以他们通过给cmpsub几乎相同的编码来使这个过程变得简单,只在一个比特上有所不同。例如,sub %reg, %reg/mem的操作码是28h/29h,cmp %reg, %reg/mem的操作码是38h/39h,区别只是位4。这1位只是告诉CPU是将结果写入目标操作数还是丢弃它。

这使得cmpsub的形式完全相同:

  • 我们有sub %reg, %reg所以有cmp %reg, %reg

  • 我们有sub %reg, mem所以有cmp %reg, mem

  • 我们sub mem, %regcmp mem, %reg

  • 我们有sub $imm, %reg所以有cmp $imm, %reg

  • 甚至有一个特殊的短编码sub $imm, %al/%ax/%eax/%raxcmp $imm, %al/%ax/%eax/%rax并行。

但是没有sub %reg, $imm的编码,因为那将是无意义的,所以cmp %reg, $imm将需要一个新的编码,而这个编码不会与sub的现有编码并行。设计者大概决定不浪费解码晶体管和操作码空间来创建一个,因为毕竟它不会真正提供任何新功能:cmp实际上总是与条件跳转(或后来的条件集)结合使用,在这种情况下,您总是可以通过使用cmp $imm, %reg并在随后的条件跳转/集中反转测试来实现相同的事情。

相关内容

  • 没有找到相关文章

最新更新