cmpq比较什么? [英] What does cmpq compare?

查看:405
本文介绍了cmpq比较什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

谜题具有以下功能签名:

mystery has this function signature:

int mystery(char *, int);

这是神秘函数的汇编代码:

This is the mystery function assembly code:

mystery:
        movl    $0, %eax                ;set eax to 0
        leaq    (%rdi, %rsi), %rcx      ; rcx = rdi + rsi

loop:
        cmpq    %rdi, %rcx
        jle     endl
        decq    %rcx
        cmpb    $0x65, (%rcx)
        jne     loop
        incl    %eax
        jmp     loop

endl:
        ret

这行cmpq %rdi, %rcx比较什么?地址或字符值?如果要比较存储在寄存器中的地址,那又有什么意义呢?如果一个地址大于另一个地址,那么呢?

What does this line cmpq %rdi, %rcx compare? The address or the character value? If it is comparing the address stored inside the registers, what's the point though? If one address is greater than the other, so?

推荐答案

类似于memrchr ,其中cmpq检查搜索位置返回到缓冲区的开头,并且cmpb检查匹配的字节.

Looks like memrchr, with the cmpq checking for the search position getting back to the start of the buffer, and the cmpb checking for a matching byte.

cmp只是根据dst - src设置标志,就像sub 一样.因此,它当然会比较其输入操作数.在这种情况下,它们都是持有指针的qword寄存器.

cmp just sets FLAGS according to dst - src, exactly like sub. So it compares its input operands, of course. In this case they're both qword registers holding pointers.

我不建议使用jle进行地址比较;最好将地址视为未签名.尽管对于x86-64而言,实际上并不重要;您不能有一个跨越有符号溢出边界的数组,因为那里存在非规范的孔". 在64-位x86?

I wouldn't recommend jle for address comparison; better to treat addresses as unsigned. Although for x86-64 it doesn't actually matter; you can't have an array that spans the signed-overflow boundary because the non-canonical "hole" is there. Should pointer comparisons be signed or unsigned in 64-bit x86?

不过,jbe会更有意义.除非您实际上具有从最高地址到最低地址跨越边界的数组,否则指针将从0xfff...fff换为0.但是无论如何,您可以通过执行if (p == start) break而不是p <= start来解决此错误.

Still, jbe would make more sense. Unless you actually have arrays that span across the boundary from the highest address to the lowest address, so the pointer wraps from 0xfff...fff to 0. But anyway, you could fix this bug by doing if (p == start) break instead of p <= start.

此函数中有一个错误,假设它是为x86-64 System V ABI编写的:其签名的大小为int arg,但假定其符号扩展为指针char *endp = start + len时的宽度.

There is a bug in this function though, assuming it's written for the x86-64 System V ABI: its signature takes an int size arg, but it assumes its sign-extended to pointer width when it does char *endp = start + len.

ABI允许窄arg在其寄存器的高位中具有垃圾.

The ABI allows narrow args to have garbage in the high bits of their register. Is a sign or zero extension required when adding a 32bit offset to a pointer for the x86-64 ABI?

此操作还存在一些主要的性能问题:一次检查1个字节是总垃圾,而SSE2一次检查16个字节.而且,它不使用任何一个条件分支作为循环分支,因此它每次迭代有3次跳转,而不是2次.即,有一个额外的未使用的条件分支.

There are also major performance problems with this: checking 1 byte at a time is total garbage vs. SSE2 16 bytes at a time. Also, it doesn't use either conditional branch as the loop branch, so it has 3 jumps per iteration instead of 2. i.e. an extra not-taken conditional branch.

此外,它在循环后减去指针,而不是在循环内浪费inc %eax.如果要在循环内执行inc %eax,则最好检查它的大小,而不是指针比较.

Also, it pointer-subtract after the loop instead of wasting an inc %eax inside the loop. If you're going to do inc %eax inside the loop, you might as well check the size against it instead of the pointer compare.

无论如何,编写该函数的目的是为了易于逆向工程,而不是高效. jmp以及2个条件分支使该IMO变得更糟,而不是底部有条件的惯用循环.

Anyway, the function is written to be easy to reverse engineer, not to be efficient. The jmp as well as 2 conditional branches makes it worse for that IMO, vs. an idiomatic loop with a condition at the bottom.

这篇关于cmpq比较什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆