这是一个传递字符串作为输入的程序。
我对下面显示的汇编代码(特别是第6行)感到困惑。 这是我从研究中了解到的:
rbp-48
是一个指针,指向存储argv
的堆栈地址。 (argv
本身就是指向argv
数组开头的地址)argv
数组地址。argv[1]
的地址。 (我知道argv[1]
内还有一个指向字符串的地址)。现在让我感到困惑:如果我想访问argv[1]
中的第一个字符并将其存储在eax寄存器中,我希望汇编程序执行以下操作:
mov eax, BYTE PTR [rdx]
如果我需要访问argv [1]中存储的第二个字符并将其存储在eax寄存器中,则我希望汇编程序执行以下操作:
mov eax, BYTE PTR [rdx+1]
但是,相反,我看到编译器执行以下操作:
add rax, rdx
我不明白该指令如何使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
答案 0 :(得分:2)
哦,我终于弄明白了你的困惑。在有问题的指令处,rax不再包含argv;它被重新加载了i的值。编译器使用add
指令而不是索引寻址模式。
eax是rax的低32位。加载eax时,该值将零扩展为64位。
然后cdqe
将EAX符号扩展为RAX,因为i
是用于索引指针的32位带符号整数。通过加载
可以简化编译器
movsx rax, dword ptr [rbp-24]
。