我正在阅读系统调用的以下定义:
.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
我看到它解释了行cmpq $-4095 %rax
确定%rax是否包含介于-1和-4095之间的值。它是如何做到的? cmpq指令究竟做了什么?
答案 0 :(得分:17)
cmpq $-4095, %rax
将64位寄存器%rax与立即值-4095
进行比较 - 为了进行比较,将值符号扩展为64位。即,-4095
具有64位2的补码表示:ffff ffff ffff f001
cmp
指令设置标志寄存器,因为第一个“{second”和第一个'的第二个操作数的sub
(减法)在AT& T语法中被反转。实际上,标志是根据以下结果设置的:(RAX - (- 4095))
或(RAX + 4095)
,在2的补码中是相同的。
其中一个标志集是进位标志(CF),它被设置为(无符号)溢出。 jae
指令(跳转 - 如果高于或等于)实际上是jnc
的“别名”(如果不是进位则跳转)。换句话说,如果(RAX + 4095)
不携带,则采取分支。在2的补码中,对于范围为RAX
的{{1}}的值,情况也是如此。 (记住2的补码运算如何包装)。
说明,包括[-4095, -1]
和cmp
(或jae
),请参阅:Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 2。
[E] FLAGS寄存器(以及算术标志表示的内容)在Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 1的第3.4.3节中描述。