我在逐个字符的比较中比较两个数组,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应该具有相同的效果。
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]
加载单个字节,零扩展到更宽的寄存器。