arrays - x86-64 汇编中的数组元素比较(AT&T 语法)

标签 arrays assembly x86-64 att

我正在尝试在 x86-64 程序集中编写一个简单的过程,它仅返回整数数组的长度。数组中的最后一个元素是 0,不应计算在内。该数组作为 int * 从 C 代码传入。

我的汇编代码如下:

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 将产生零,因此将设置零标志,但这似乎没有发生。

我可以任意将数组的任何元素加载到%rax中,它返回正确的值:

movq   (%rdi,%rax,4), %rax   # %rax initially 0, so first element loaded into %rax

任何帮助将不胜感激!

最佳答案

int 在 x86-64 ABI(SystemV 和 Windows)中都是 32 位(4 字节)。 (有关详细信息,请参阅 标签 wiki)。

cmpq $0, (%rdi,%rax,4) 正确地将索引缩放 4,但错误地使用 64 位操作数大小。 (q 代表四字。在英特尔的 x86 术语中,一个“字”是 16 位。)

cmpq 正在比较两个连续元素。等效的 C 语言为 while( 0 != *(int64_t*)&(array[i]) ){++i; }


在 x86 之外,一个字通常是机器的寄存器大小或类似的东西,因此它与 long 的大小匹配。例如在 32 位 MIPS 上,一个字是 32 位。

这只是术语,有方便的名称很方便,例如 word(AT&T 语法 w 后缀)、dword(l 后缀)、qword(q 后缀)。

gdb 中,即使在调试 x86 时,某些地方“word”也是 32 位(例如转储内存的 x 命令有 b (字节)、h(半字:16b)、w(字)和g(巨人:8B)大小格式说明符。

关于arrays - x86-64 汇编中的数组元素比较(AT&T 语法),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37018454/

相关文章:

performance - 为什么 SSE 标量 sqrt(x) 比 rsqrt(x) * x 慢?

c - 内联汇编 : move imm to a 64-bit register without sign-extension

assembly - 将64位寄存器的高32位清零

c# - c#中带有字符串键的数组数组

python - numpy 数组连接错误 : 0-d arrays can't be concatenated

javascript - 在前 N 个自然数的数组中找到 1、2、3 个缺失的数字

c - 如何在x86-64架构上使用INVLPG?

Php字符串根据字符与字符串条件匹配来分解字符串

assembly - 没有保护模式的 CPU 中的保护

assembly - 无效的有效地址计算