Почему я добавляю rax и rdx? - PullRequest
       22

Почему я добавляю rax и rdx?

0 голосов
/ 26 сентября 2018

Это программа, которой передается строка в качестве ввода.

Я запутался в коде ассемблера, показанном ниже, в частности в строке 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 икод ассемблера corrв соответствии с инструкциями цикла:

#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 голосов
/ 26 сентября 2018

О, я наконец-то понял твоё замешательство.На момент рассматриваемой инструкции rax больше не содержит argv;он был перезагружен со значением i.Компилятор использует инструкцию add вместо режима индексированной адресации.

eax - это младшие 32 бита rax.Когда загружается eax, значение расширяется от нуля до 64 бит.

А затем cdqe расширяет знак EAX до RAX, потому что i - это 32-разрядное целое число со знаком, которое вы используете дляиндексировать указательКомпилятор мог бы упростить загрузку с
movsx rax, dword ptr [rbp-24].

...