x86-64 访问数组元素
x86-64 accessing element of array
你好我是汇编语言的初学者,movl (%rdi,%r12), %r10d
和movl (%rdi,%r12,4), %r10d
有区别吗?我尝试了他们两个,他们似乎都在做同样的工作——将 %rdi 的元素在 %r12 位置保存到 %r10d。第二个例子中的4真的有必要吗?
是的,它们是不同的。
例如假设 %rdi = 0x12340000
和 %r12 = 8
。然后 movl (%rdi,%r12), %r10d
将 %r12
添加到 %rdi
以形成有效地址,因此您从地址 0x12340008
加载一个 32 位双字。 4
为SIB寻址方式的比例参数;它会导致 %r12
在添加到 %rdi
之前乘以 4,因此使用 movl (%rdi,%r12,4), %r10d
您可以从地址 0x12340020
加载一个 32 位双字。
参见GNU as manual:“如果没有指定scale
,scale
被认为是1。”
如果您尝试使用定义为
的数组
int32_t foo[] = {1,3,5,7,9,11,13,15,17,19,21,23,25};
和%rdi
包含foo
的地址,如上%r12 = 8
,则movl (%rdi,%r12), %r10d
将加载%r10d
的值为5
,但 movl (%rdi,%r12,4), %r10d
将使用值 17
加载它。换句话说,问题在于您是将 %rdi
视为字节计数还是 32 位整数计数。
如果它们在您的测试中看起来工作相同,那么要么您的测试有问题,要么两个不同的地址碰巧包含相同的值,或者您的 %r12
为零,或者您的汇编程序坏了(不太可能)。
你好我是汇编语言的初学者,movl (%rdi,%r12), %r10d
和movl (%rdi,%r12,4), %r10d
有区别吗?我尝试了他们两个,他们似乎都在做同样的工作——将 %rdi 的元素在 %r12 位置保存到 %r10d。第二个例子中的4真的有必要吗?
是的,它们是不同的。
例如假设 %rdi = 0x12340000
和 %r12 = 8
。然后 movl (%rdi,%r12), %r10d
将 %r12
添加到 %rdi
以形成有效地址,因此您从地址 0x12340008
加载一个 32 位双字。 4
为SIB寻址方式的比例参数;它会导致 %r12
在添加到 %rdi
之前乘以 4,因此使用 movl (%rdi,%r12,4), %r10d
您可以从地址 0x12340020
加载一个 32 位双字。
参见GNU as manual:“如果没有指定scale
,scale
被认为是1。”
如果您尝试使用定义为
的数组int32_t foo[] = {1,3,5,7,9,11,13,15,17,19,21,23,25};
和%rdi
包含foo
的地址,如上%r12 = 8
,则movl (%rdi,%r12), %r10d
将加载%r10d
的值为5
,但 movl (%rdi,%r12,4), %r10d
将使用值 17
加载它。换句话说,问题在于您是将 %rdi
视为字节计数还是 32 位整数计数。
如果它们在您的测试中看起来工作相同,那么要么您的测试有问题,要么两个不同的地址碰巧包含相同的值,或者您的 %r12
为零,或者您的汇编程序坏了(不太可能)。