src 或 destination 中两个值的汇编语言含义
Assembly language meaning of two values in src or destination
例如,和
有什么区别
cmpl [=10=]x7, 0x8(%rsp)
和
cmpl [=11=]x7, (%rsp)
还有cmp
和cmpl
有什么区别?
我相信您的问题的答案可以在另一个 SO 问题中找到:The difference between cmpl and cmp
AT&T 语法中 x86 上的内存操作数一般为 "offset(base, index, scale)" 其中 offset 是(常数)偏移量,base 是(基数) register,index是一个(索引)寄存器,scale是常量1、2、4或8。不过,这些字段大部分都可以被省略以获得默认值。 No offset 表示偏移量为 0。No base 表示没有 base regiser。没有 index 和 scale 表示没有索引寄存器。
在您的具体示例中,(%rsp)
表示 %rsp
作为基址寄存器,没有偏移量也没有索引。 0x8(%rsp)
表示%rsp
作为基址寄存器,0x8(8)作为偏移量。
宽度后缀
Intel 将指令助记符描述为CMP
(在Intel 64 and IA-32 Architectures software Developer's Manual中),但是指令的形式有很多种,例如如比较 8 位、16 位、32 位或 64 位数字,将立即数与内存中的值进行比较,等等。
一些汇编器使用后缀来区分操作数宽度,使用:
b
字节,
w
for word(英特尔在这些架构中使用的两个字节),
l
表示长字(四个字节),
q
for quad word(四个字,八个字节)。
如果其中一个操作数是一个寄存器,汇编程序可以计算出(至少在理论上;一些汇编程序可能没有这个功能)它的宽度。
例如,cmp [=15=]x7, %rsp
将是一个 64 位比较,因为 %rsp
命名一个 64 位寄存器。 (%esp
为32位寄存器,%sp
为16位寄存器。)
操作数形式
cmpl [=19=]x7, (%rsp)
表示立即数 0x7
与内存中 %rsp
寄存器中包含的地址处的数据进行 32 位比较。
没有l
后缀,这条指令的宽度是未知的。 0x7
是立即数。与 C 不同,它没有默认类型。
类似地,(%rsp)
是内存中没有关联类型的位置。所以需要 l
。 (注意这里的区别:cmp [=26=]x7, %rbp
会将 7 与 %rbp
中的值进行比较,而 cmp [=28=]x7, (%rbp)
会将 7 与内存中位于 %rbp
中地址的值进行比较。)
8(%rsp)
表示(%rsp)
加8得到的地址。
更完整的形式是 offset(base, index, scale),表示base(这是一个寄存器)中的地址加上index(另一个寄存器)乘以scale(常数 1、2、4 或 8)加上 offset.
这种形式用于索引数组:假设一个数组从地址 %rax
开始并且有 4 个字节宽的元素,并且您想要索引在 %rbx
中的元素。然后你用 (%rax, %rbx, 4)
来解决这个元素。可以添加额外的偏移量以引用数组中结构内的成员或调整数组相对于 %rax
.
的基地址
例如,和
有什么区别cmpl [=10=]x7, 0x8(%rsp)
和
cmpl [=11=]x7, (%rsp)
还有cmp
和cmpl
有什么区别?
我相信您的问题的答案可以在另一个 SO 问题中找到:The difference between cmpl and cmp
AT&T 语法中 x86 上的内存操作数一般为 "offset(base, index, scale)" 其中 offset 是(常数)偏移量,base 是(基数) register,index是一个(索引)寄存器,scale是常量1、2、4或8。不过,这些字段大部分都可以被省略以获得默认值。 No offset 表示偏移量为 0。No base 表示没有 base regiser。没有 index 和 scale 表示没有索引寄存器。
在您的具体示例中,(%rsp)
表示 %rsp
作为基址寄存器,没有偏移量也没有索引。 0x8(%rsp)
表示%rsp
作为基址寄存器,0x8(8)作为偏移量。
宽度后缀
Intel 将指令助记符描述为CMP
(在Intel 64 and IA-32 Architectures software Developer's Manual中),但是指令的形式有很多种,例如如比较 8 位、16 位、32 位或 64 位数字,将立即数与内存中的值进行比较,等等。
一些汇编器使用后缀来区分操作数宽度,使用:
b
字节,w
for word(英特尔在这些架构中使用的两个字节),l
表示长字(四个字节),q
for quad word(四个字,八个字节)。
如果其中一个操作数是一个寄存器,汇编程序可以计算出(至少在理论上;一些汇编程序可能没有这个功能)它的宽度。
例如,cmp [=15=]x7, %rsp
将是一个 64 位比较,因为 %rsp
命名一个 64 位寄存器。 (%esp
为32位寄存器,%sp
为16位寄存器。)
操作数形式
cmpl [=19=]x7, (%rsp)
表示立即数 0x7
与内存中 %rsp
寄存器中包含的地址处的数据进行 32 位比较。
没有l
后缀,这条指令的宽度是未知的。 0x7
是立即数。与 C 不同,它没有默认类型。
类似地,(%rsp)
是内存中没有关联类型的位置。所以需要 l
。 (注意这里的区别:cmp [=26=]x7, %rbp
会将 7 与 %rbp
中的值进行比较,而 cmp [=28=]x7, (%rbp)
会将 7 与内存中位于 %rbp
中地址的值进行比较。)
8(%rsp)
表示(%rsp)
加8得到的地址。
更完整的形式是 offset(base, index, scale),表示base(这是一个寄存器)中的地址加上index(另一个寄存器)乘以scale(常数 1、2、4 或 8)加上 offset.
这种形式用于索引数组:假设一个数组从地址 %rax
开始并且有 4 个字节宽的元素,并且您想要索引在 %rbx
中的元素。然后你用 (%rax, %rbx, 4)
来解决这个元素。可以添加额外的偏移量以引用数组中结构内的成员或调整数组相对于 %rax
.