x86-64 汇编中的数组元素比较(AT&T 语法)
Array element comparison in x86-64 Assembly (AT&T syntax)
我正在尝试在 x86-64 程序集中编写一个简单的过程,它只是 returns 一个整数数组的长度。数组中的最后一个元素是一个 0,不应该被计算在内。该数组作为 int * 从 C 代码传入。
我的汇编代码如下:
f1:
movq [=10=], %rax # zero out %rax
jmp test # jump to test
body:
incq %rax # increment %rax, which is counter and array index
test:
cmpq [=10=], (%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 将产生一个零,因此将设置零标志,但这似乎没有发生。
我可以任意加载数组的任何元素到 %rax 中,returns 正确的值:
movq (%rdi,%rax,4), %rax # %rax initially 0, so first element loaded into %rax
如有任何帮助,我们将不胜感激!
int
在两个 x86-64 ABI(SystemV 和 Windows)中都是 32 位(4 字节)。 (有关详细信息,请参阅 x86 标签 wiki)。
cmpq [=11=], (%rdi,%rax,4)
正确地将索引缩放 4, 但错误地使用了 64 位操作数大小。 (q
代表四字。在英特尔的 x86 术语中,"word" 是 16 位。)
cmpq
正在比较两个连续的元素。等效的 C 将是 while( 0 != *(int64_t*)&(array[i]) ){ ++i; }
在 x86 之外,一个字通常是机器的寄存器大小或类似的东西,所以它匹配 long
的大小。例如在 32 位 MIPS 上一个字是 32 位。
这只是术语,起个方便的名字就好了,比如word(AT&T语法w
后缀),dword(l
后缀),qword(q
后缀)。
在gdb
中,在某些地方"word"即使在调试x86时也是32位的(例如x
转储内存的命令有b
(字节),h
(半字:16b)、w
(字)和 g
(巨型:8B)大小格式说明符。
我正在尝试在 x86-64 程序集中编写一个简单的过程,它只是 returns 一个整数数组的长度。数组中的最后一个元素是一个 0,不应该被计算在内。该数组作为 int * 从 C 代码传入。
我的汇编代码如下:
f1:
movq [=10=], %rax # zero out %rax
jmp test # jump to test
body:
incq %rax # increment %rax, which is counter and array index
test:
cmpq [=10=], (%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 将产生一个零,因此将设置零标志,但这似乎没有发生。
我可以任意加载数组的任何元素到 %rax 中,returns 正确的值:
movq (%rdi,%rax,4), %rax # %rax initially 0, so first element loaded into %rax
如有任何帮助,我们将不胜感激!
int
在两个 x86-64 ABI(SystemV 和 Windows)中都是 32 位(4 字节)。 (有关详细信息,请参阅 x86 标签 wiki)。
cmpq [=11=], (%rdi,%rax,4)
正确地将索引缩放 4, 但错误地使用了 64 位操作数大小。 (q
代表四字。在英特尔的 x86 术语中,"word" 是 16 位。)
cmpq
正在比较两个连续的元素。等效的 C 将是 while( 0 != *(int64_t*)&(array[i]) ){ ++i; }
在 x86 之外,一个字通常是机器的寄存器大小或类似的东西,所以它匹配 long
的大小。例如在 32 位 MIPS 上一个字是 32 位。
这只是术语,起个方便的名字就好了,比如word(AT&T语法w
后缀),dword(l
后缀),qword(q
后缀)。
在gdb
中,在某些地方"word"即使在调试x86时也是32位的(例如x
转储内存的命令有b
(字节),h
(半字:16b)、w
(字)和 g
(巨型:8B)大小格式说明符。