如何比较x86-64中的两个寄存器

问题描述 投票:1回答:1

我在逐个字符的比较中比较两个数组,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是extern,在C中定义为“char array1 [vector]”。根据我的理解,array1 [i]是16位长,因为它是一个char数组,而char是一个int == 16位。因此,首先我尝试使用完整的64位寄存器进行操作,例如:

cmp rdx, rax

如果我使用64位寄存器(零位未设置,因此jne被触发并且如果结束),代码将失败,它仅在我使用al和dl(8 lsb)时才有效,我想了解原因。

比较8 lsb并不是一个问题,因为arrayX [i]永远不会高于2 ^ 8,但是做cmp rax,rdx和cmp al,dl应该具有相同的效果。

assembly x86-64
1个回答
0
投票

rax是一个qword寄存器,8个字节= 64位。

char是8位= 1字节,而不是16位。 (对于64位x86编译器,int是32位类型。如果你很好奇,请查看编译器生成的代码。)

如果你一次加载8个字符并将整个qword寄存器与cmp rdx, rax进行比较,它类似于memcmp(array1+i, array2+i, 8)(但实际上实现memcmp会使用bswap,因为x86是小端,但对于memcmp,第一个区别是重要的。)

您当前的代码有效,因为即使加载8个字节,您也只能查看低单字节部分寄存器。

但是如果你给它一个指向页面中最后一个字符的指针,并且下一个内存页面未被映射,你的程序就会出错。从最后一个字符的地址开始的8字节加载将进入未映射的页面和段错误。

使用movzx eax, byte [rdi]加载单个字节,零扩展到更宽的寄存器。

© www.soinside.com 2019 - 2024. All rights reserved.