【发布时间】:2020-10-19 21:41:05
【问题描述】:
您好,我是汇编语言初学者,movl (%rdi,%r12), %r10d 和movl (%rdi,%r12,4), %r10d 有区别吗?我尝试了它们,它们似乎都在做同样的工作——将 %r12 位置的 %rdi 元素保存到 %r10d。第二个例子中的 4 真的有必要吗?
【问题讨论】:
标签: assembly x86-64 att addressing-mode
您好,我是汇编语言初学者,movl (%rdi,%r12), %r10d 和movl (%rdi,%r12,4), %r10d 有区别吗?我尝试了它们,它们似乎都在做同样的工作——将 %r12 位置的 %rdi 元素保存到 %r10d。第二个例子中的 4 真的有必要吗?
【问题讨论】:
标签: assembly x86-64 att addressing-mode
是的,它们是不同的。
假设例如%rdi = 0x12340000 和%r12 = 8。然后movl (%rdi,%r12), %r10d 将%r12 添加到%rdi 以形成有效地址,因此您从地址0x12340008 加载一个32 位dword。 4是SIB寻址方式的尺度参数;它会导致 %r12 在添加到 %rdi 之前乘以 4,因此使用 movl (%rdi,%r12,4), %r10d 您可以从地址 0x12340020 加载一个 32 位 dword。
参见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会加载它的值@987654343 @。换句话说,问题在于您是将%rdi 视为字节计数还是32 位整数计数。
如果它们在您的测试中似乎工作相同,那么您的测试有错误,或者两个不同的地址巧合包含相同的值,或者您的 %r12 为零,或者您的汇编程序损坏(不太可能)。
【讨论】:
movb不一样。
movb (%rdi, %r12), %r10b 会从地址0x12340008 移动字节,而movb (%rdi, %r12, 4), %r10b 会从地址0x12340020 移动字节。无论操作数大小如何,比例参数的作用都相同。