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的补码运算是如何包装的).
下面的说明包括cmp和jae(或j<cond>):英特尔®64和IA-32架构软件开发人员手册,第2卷.
英特尔®64和IA-32架构软件开发人员手册第1卷第3.4.3节描述了[E] FLAGS寄存器(以及算术标志所表示的内容).