我正在尝试在x86-64程序集中编写一个简单的过程,它只返回一个int数组的长度。数组中的最后一个元素是0,不应该计算。该数组作为来自C代码的int *传入。
我的汇编代码如下:
f1:
movq $0, %rax # zero out %rax
jmp test # jump to test
body:
incq %rax # increment %rax, which is counter and array index
test:
cmpq $0, (%rdi,%rax,4) # compare (rdi + (rax * 4)) to 0
jne body # jump if zero flag is not set
ret
当这个运行时,我得到的结果不正确,但也不是非常不正确,所以不是11(数组的大小减去结尾0)我得到38.我认为发生的是我的比较语句是不正确。我的想法是,由于cmpq在不改变寄存器的情况下执行(dest-src),如果数组索引为0,则0-0将产生零,因此将设置零标志,但这似乎不会发生。< / p>
我可以随意将数组中的任何元素加载到%rax中,后者返回正确的值:
movq (%rdi,%rax,4), %rax # %rax initially 0, so first element loaded into %rax
非常感谢任何帮助!
答案 0 :(得分:2)
int
为32位(4字节)。 (有关详细信息,请参阅x86标记wiki。)
cmpq $0, (%rdi,%rax,4)
正确地将索引缩放4,但错误地使用64位操作数大小。 (q
代表四字。在Intel的x86术语中,“字”是16位。)
cmpq
正在比较两个连续的元素。等效的C将是while( 0 != *(int64_t*)&(array[i]) ){ ++i; }
在x86之外,一个单词通常是机器的寄存器大小或类似的东西,所以它匹配long
的大小。例如一个字是32位MIPS上的32位。
这只是术语,方便的名称如word(AT&amp; T语法w
后缀),dword(l
后缀),qword(q
后缀)很方便。< / p>
在gdb
中,在某些地方,即使在调试x86时,“word”也是32位(例如转储内存的x
命令有b
(字节),h
(半字:16b),w
(字)和g
(巨型:8B)尺寸格式说明符。