Как сравнить два регистра в x86-64 - PullRequest
1 голос
/ 12 апреля 2019

Я сравниваю два массива в ассемблерных символах, код C будет выглядеть примерно так:

   count=0;
   for (i=0;i<vector;i++) {
     if (array1[i]==array2[i]) {
       count++;
     }
   }

По сути, оба массива сравниваются, и когда символ в этой позиции одинаков,счет увеличен.

Я получил этот код в ассемблере, который, кажется, на самом деле работает так, как задумано:

   forEachVector:
     cmp bl, vector
     jge endforEachVector
     mov rax, QWORD[array1+rbx] ; move array[i] to rax
     mov rdx, QWORD[array2+rbx] ; move array[i] to rdx

     if1Equals2:
     cmp dl, al
     jne fi1Equals2
     inc cl
     fi1Equals2:

     inc bl
     jmp forEachVector
   endforEachVector: 

vector - константа, а array1 и 2 - внешние и определены вC как "char массив1 [вектор]".В моем понимании, array1 [i] имеет длину 16 бит, потому что это массив символов, а символ int == 16 бит.Из-за этого сначала я попытался работать с полными 64-битными регистрами, например:

cmp rdx, rax

И код не работает, если я использую 64-битные регистры (нулевой бит не установлен, поэтому jne срабатывает, и еслизаканчивается), это работает только тогда, когда я использую al и dl (8 lsb), и я хочу понять, почему.

Сравнение 8 lsb не проблема, так как arrayX [i] никогда не будет вышечем 2 ^ 8, но выполнение cmp rax, rdx и cmp al, dl должно иметь тот же эффект.

1 Ответ

0 голосов
/ 13 апреля 2019

rax - регистр слов, 8 байтов = 64 бита.

A char составляет 8 бит = 1 байт, не 16 бит. (И int - это 32-битный тип для 64-битных компиляторов x86. Посмотрите на сгенерированный компилятором код, если вам интересно.)

Если вы загружаете 8 символов за раз и сравниваете целые регистры qword с cmp rdx, rax, это похоже на memcmp(array1+i, array2+i, 8) (Но на самом деле реализация memcmp будет использовать bswap, потому что x86 мало endian, но для memcmp разница first является существенной.)

Ваш текущий код работает, потому что даже если вы загружаете 8 байт, вы смотрите только на младший однобайтовый частичный регистр.

Но ваша программа выдаст ошибку, если вы дадите ей указатель на последний символ на странице, и следующая страница памяти не будет отображена. Ваша 8-байтная загрузка с адреса этого последнего символа перешла бы на не отображенную страницу и стала бы сегфоутом.

Используйте movzx eax, byte [rdi] для загрузки одного байта, расширенного нулями до более широкого регистра.

...