为什么要添加rax和rdx?

时间:2018-09-26 02:14:20

标签: c assembly x86-64

这是一个传递字符串作为输入的程序。

我对下面显示的汇编代码(特别是第6行)感到困惑。 这是我从研究中了解到的:

  • rbp-48是一个指针,指向存储argv的堆栈地址。 (argv本身就是指向argv数组开头的地址)
  • 现在rax寄存器存储argv数组地址。
  • 然后我们将8个字节添加到rax。这意味着rax现在指向argv[1]的地址。 (我知道argv[1]内还有一个指向字符串的地址)。
  • 然后,我们访问argv [1]中存储的值,并将其存储在rdx寄存器中。这意味着rdx现在指向字符串开头的地址。
  • 然后我们将[rbp-24] = i计数器变量移至eax寄存器。
  • 然后我们有一个动作cdqe,我认为这是不相关的。

现在让我感到困惑:如果我想访问argv[1]中的第一个字符并将其存储在eax寄存器中,我希望汇编程序执行以下操作:

mov   eax, BYTE PTR [rdx]

如果我需要访问argv [1]中存储的第二个字符并将其存储在eax寄存器中,则我希望汇编程序执行以下操作:

mov   eax, BYTE PTR [rdx+1]

但是,相反,我看到编译器执行以下操作:

add     rax, rdx
  • 将字符串开始的内存地址添加到存储指向字符串开头的地址的内存地址中,并将此结果保存在rax中。

我不明白该指令如何使rax指向argv [1]中的任何字符。

下面是与循环指令相对应的C代码和汇编代码:

#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
int sum = 0;
for(int i = 0; i < strlen(argv[1]); i ++){
  sum += (int)argv[1][i];
}
return 0;
}

组装

mov     rax, QWORD PTR [rbp-48]
add     rax, 8
mov     rdx, QWORD PTR [rax]
mov     eax, DWORD PTR [rbp-24]
cdqe
add     rax, rdx
movzx   eax, BYTE PTR [rax]
movsx   eax, al
add     DWORD PTR [rbp-20], eax
add     DWORD PTR [rbp-24], 1

1 个答案:

答案 0 :(得分:2)

哦,我终于弄明白了你的困惑。在有问题的指令处,rax不再包含argv;它被重新加载了i的值。编译器使用add指令而不是索引寻址模式。

eax是rax的低32位。加载eax时,该值将零扩展为64位。

然后cdqe将EAX符号扩展为RAX,因为i是用于索引指针的32位带符号整数。通过加载
可以简化编译器 movsx rax, dword ptr [rbp-24]

相关问题