我在汇编中有多个非常小的问题,这些问题也是相关的,所以我在这个问题中收集了它们,而不是打开多个问题并在论坛上发垃圾邮件。
所有问题都与汇编语言语法有关:
-
为什么我不能这样写:
cmp %eax, $0x2 jg goHere
为什么它不允许做比较操作(结果不保存在一个操作数中,所以不允许它没有意义…)注意:我知道我可以通过颠倒顺序来解决这个问题,并执行jl
而不是jg
。
att语法这是应该检查是否大于0 x2 % eax。
-
为什么我可以写:
mov $41, %rax
当我不能写:
mov ($41), %rax
这很奇怪,有人告诉我在汇编中使用大括号并不重要。
-
在内存中保存字符串时,我们写入"ABC"在地址0x100中,内存应该是什么样子的:
0x100 - A0x101 - B0x102 - C
0x100 - C0x101 - B0x102 - A
For 1,我对x86的原始设计没有特别的了解,但我怀疑我们没有cmp %reg, $imm
的原因是因为cmp
和sub
之间的关系。指令cmp $imm, %reg
的行为与sub $imm, %reg
完全相同,唯一的例外是cmp
的减法结果不会写入目标%reg
,而是被丢弃。但是减法的结果仍然由CPU内部计算,并用于设置标志。(至少这在概念上是正确的,早期的cpu几乎肯定会做完整的减法;现代cpu可能有一些我不知道的优化)
所以这意味着一旦你有了sub
,cmp
几乎可以免费实现。你可以使用几乎完全相同的电路和/或微码。但是你仍然需要解码指令,所以他们通过给cmp
和sub
几乎相同的编码来使这个过程变得简单,只在一个比特上有所不同。例如,sub %reg, %reg/mem
的操作码是28h/29h,cmp %reg, %reg/mem
的操作码是38h/39h,区别只是位4。这1位只是告诉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
并在随后的条件跳转/集中反转测试来实现相同的事情。