cmpq指令有什么作用?

bro*_*s94 12 x86 assembly x86-64

我正在阅读syscall的以下定义:

.text
.globl syscall
.type   syscall,%function
.align 16
syscall:
    movq %rdi, %rax     /* Syscall number -> rax.  */
    movq %rsi, %rdi     /* shift arg1 - arg5.  */
    movq %rdx, %rsi
    movq %rcx, %rdx
    movq %r8, %r10
    movq %r9, %r8
    movq 8(%rsp),%r9    /* arg6 is on the stack.  */
    syscall         /* Do the system call.  */
    cmpq $-4095, %rax   /* Check %rax for error.  */
    jae __syscall_error     /* Branch forward if it failed.  */
    ret         /* Return to caller.  */

.size syscall,.-syscall
Run Code Online (Sandbox Code Playgroud)

我看到它解释说该行cmpq $-4095 %rax确定%rax是否包含介于-1和-4095之间的值.它是如何做到的?cmpq指令究竟做了什么?

Bre*_*ale 18

cmpq $-4095, %rax将64位寄存器%rax与立即值进行比较-4095- 为了进行比较,将值符号扩展为64位.即,-4095具有64位2的补码表示:ffff ffff ffff f001

cmp指令设置标志寄存器,因为它将sub第一个 - 第二个操作数的(减法)从第一个 - "第二个"和"第一个"在AT&T语法中反转.实际上,标志是根据以下结果设置的:(RAX - (- 4095))或者(RAX + 4095)在2的补码中是相同的.

其中一个标志是进位标志(CF),它被设置为(无符号)溢出.的jae指令(跳转-IF-上述或相等的)实际上是用于"变体" jnc(跳跃-IF-不进位).换句话说,分支被采用,如果(RAX + 4095)没有携带.在2的补码中,对于RAX范围中的值,这将是真实的:[-4095, -1].(记住2的补码运算是如何包装的).


下面的说明包括cmpjae(或j<cond>):英特尔®64和IA-32架构软件开发人员手册,第2卷.

英特尔®64和IA-32架构软件开发人员手册第1卷第3.4.3节描述了[E] FLAGS寄存器(以及算术标志所表示的内容).