汇编中的 At&t 语法?
At&t syntax in Assembly?
我在汇编中有多个非常小的问题,它们也相关,所以我将它们收集在这个问题中,而不是打开多个问题并在论坛上发垃圾邮件。
所有问题都与 Assembly At&t 语法有关:
为什么我不能写这样的东西:
cmp %eax, [=10=]x2
jg goHere
为什么它不允许进行比较操作(结果未保存在其中一个操作数中,因此不允许它没有意义...)注意:我知道我可以通过以下方式解决此问题颠倒顺序并执行 jl
而不是 jg
.
在 att 语法中,这应该检查 0x2 是否大于 %eax。
为什么我会写:
mov , %rax
虽然我不会写:
mov (), %rax
这很奇怪,有人告诉我在汇编中使用大括号并不重要。
当在内存中保存一个字符串时,假设地址 0x100 中的“ABC”内存应该是这样的:
0x100 - 一个
0x101-B
0x102 - C
0x100-C
0x101-B
0x102-A
对于1,我对x86的原始设计没有特别了解,但我怀疑我们没有cmp %reg, $imm
的原因是因为cmp
和[=之间的关系12=]。指令 cmp $imm, %reg
的行为与 sub $imm, %reg
完全相同,唯一的例外是 cmp
的减法结果不会写入目标 %reg
,而是被丢弃。但是减法的结果仍然由 CPU 内部计算并用于设置标志。 (至少这在概念上是正确的,早期的 CPUs 几乎肯定做了完全减法;现代 CPUs 可能有一些我不知道的优化。)
所以这意味着一旦您拥有 sub
,cmp
几乎可以免费实施。您可以使用几乎完全相同的电路 and/or 微代码。但是您仍然需要对指令进行解码,因此他们通过为 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
的现有编码平行.设计师大概决定不浪费解码晶体管和操作码 space 来创建一个,因为毕竟它不会真正提供任何新功能:cmp
实际上总是与条件跳转(或稍后,条件集),在这种情况下,您始终可以通过使用 cmp $imm, %reg
并在后续条件 jump/set.
中反转测试来实现相同的目的
我在汇编中有多个非常小的问题,它们也相关,所以我将它们收集在这个问题中,而不是打开多个问题并在论坛上发垃圾邮件。
所有问题都与 Assembly At&t 语法有关:
为什么我不能写这样的东西:
cmp %eax, [=10=]x2 jg goHere
为什么它不允许进行比较操作(结果未保存在其中一个操作数中,因此不允许它没有意义...)注意:我知道我可以通过以下方式解决此问题颠倒顺序并执行 jl
而不是 jg
.
在 att 语法中,这应该检查 0x2 是否大于 %eax。
为什么我会写:
mov , %rax
虽然我不会写:
mov (), %rax
这很奇怪,有人告诉我在汇编中使用大括号并不重要。
当在内存中保存一个字符串时,假设地址 0x100 中的“ABC”内存应该是这样的:
0x100 - 一个 0x101-B 0x102 - C
0x100-C 0x101-B 0x102-A
对于1,我对x86的原始设计没有特别了解,但我怀疑我们没有cmp %reg, $imm
的原因是因为cmp
和[=之间的关系12=]。指令 cmp $imm, %reg
的行为与 sub $imm, %reg
完全相同,唯一的例外是 cmp
的减法结果不会写入目标 %reg
,而是被丢弃。但是减法的结果仍然由 CPU 内部计算并用于设置标志。 (至少这在概念上是正确的,早期的 CPUs 几乎肯定做了完全减法;现代 CPUs 可能有一些我不知道的优化。)
所以这意味着一旦您拥有 sub
,cmp
几乎可以免费实施。您可以使用几乎完全相同的电路 and/or 微代码。但是您仍然需要对指令进行解码,因此他们通过为 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
的现有编码平行.设计师大概决定不浪费解码晶体管和操作码 space 来创建一个,因为毕竟它不会真正提供任何新功能:cmp
实际上总是与条件跳转(或稍后,条件集),在这种情况下,您始终可以通过使用 cmp $imm, %reg
并在后续条件 jump/set.