【问题标题】:At&t syntax in Assembly?汇编中的 At&t 语法?
【发布时间】:2021-11-25 12:21:14
【问题描述】:

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

所有问题都与Assembly At&t 语法有关:

  1. 为什么我不能写类似的东西:

     cmp %eax, $0x2
     jg goHere
    

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

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

  1. 为什么我会写作:

     mov $41, %rax
    

    虽然我不会写:

     mov ($41), %rax
    

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

  1. 在内存中保存字符串时,假设地址 0x100 中的“ABC”,内存应该是什么样子:

    0x100 - A 0x101 - B 0x102 - C

    0x100 - C 0x101 - B 0x102 - A

【问题讨论】:

  • 请尝试每个问题只问一个问题。至于(1),没有操作数以其他顺序排列的指令。对于 (2),括号表示从名为 $41 的符号加载的内存操作数。如果要分组,请将括号放在美元符号后面,例如$(41)
  • 对于(3),字符串的第一个字节在最低地址。
  • @fuz 第一个字节来自哪个方向? for 1 我问为什么没有这样的命令? 2 你没有回答为什么它不起作用......
  • "注意:我知道我可以通过颠倒顺序并使用jl 而不是jg 来解决这个问题。" jg 的倒数实际上是jle 或其别名jng。另外,请注意,条件位于两个操作数 in Intel order 之间。如果eax 大于(有符号)2,cmp $2, %eax \ jg 将跳转。(Intel 订单为相同的机器代码提供cmp eax, 2。)
  • @Dan 第一个字节是字符“A”。至于(1)我不知道,问8086处理器的厂商。这可能是因为这样的指令是多余的。对于(2),指令确实有效(如它汇编)。它只是做了一些超出你预期的事情,我想我已经解释了它的作用。

标签: assembly x86-64 att gnu-assembler


【解决方案1】:

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

所以这意味着一旦您拥有subcmp 几乎可以免费实现。您可以使用几乎完全相同的电路和/或微码。但是您仍然必须对指令进行解码,因此他们也通过为cmp 提供与sub 几乎相同的编码来简化此操作,仅在一位不同。例如,sub %reg, %reg/mem 是操作码 28h/29h,cmp %reg, %reg/mem 是操作码 38h/39h,只是第 4 位不同。那一位只是向 CPU 发出信号,是将结果写入目标操作数还是丢弃它。

这使得给cmp 提供与sub 完全相同的形式很自然:

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

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

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

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

  • 甚至还有一个特殊的短编码sub $imm, %al/%ax/%eax/%rax,它有一个平行的cmp $imm, %al/%ax/%eax/%rax

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

【讨论】:

  • cmp 和 sub 之间并没有什么特殊关系,更多的是 cmp 不是特殊的,并且与所有其他 2 操作数 ALU 指令具有相同的形式回到8086,包括subaddxor等,包括no-modrmcmp $imm8, %alcmp $imm16, %ax形式。所以是的,正如你所说的没有直接目的地,因为其他 ALU 指令都 RMW 他们的“目的地”,不值得特别封装一个额外的操作码。奇怪的是test,它缺少test $sign_extended_imm8, r/m16 表单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-02
相关资源
最近更新 更多