首页 文章

我为什么要添加rax和rdx?

提问于
浏览
0

这是一个传递String作为输入的程序 .

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

  • rbp-48 是一个指向存储 argv 的堆栈地址的指针 . ( argv 本身,是指向 argv 数组开头的地址)

  • 现在rax寄存器存储 argv 数组地址 .

  • 然后我们向rax添加8个字节 . 这意味着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 回答

  • 2

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

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

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

相关问题