2012-05-14 32 views
7

我想检查在glibc中执行系统调用的代码。我发现了这样的事情。syscall是x86_64上的一条指令吗?

ENTRY (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_LABEL /* Jump to error handler if error. */ 
L(pseudo_end): 
    ret   /* Return to caller. */ 

现在我的问题是如果系统调用(在cmpq指令之前)是一条指令?其次,如果它是一条指令,那么ENTRY(系统调用)的含义是什么? ENTRY的相同名称(我不知道ENTRY是什么)和指令?其次,什么是L(pseudo_end)?

+0

是的。它与x86中的int 0x80相同。 – Dave

+0

请注意,通常使用专用代码来进行每次系统调用,从常量(保存寄存器)设置'%rax',并跳过设置未使用的参数。 – o11c

回答

3

是的,syscall是x86-64上的指令。在i686上有类似的指令sysenter

ENTRY(syscall)将是一个宏。可能扩展到符号定义,你必须为此而努力。

7

syscall是x86-64中的指令,用作ABI for making system calls的一部分。 (32位ABI使用int 80hsysenter,并且也可以在64位模式下使用,但使用64位代码中的32位ABI是一个坏主意,尤其是对于带指针参数的调用。)

但是也有一个C library function named syscall(2),这是系统调用ABI的通用包装器。您的代码显示该函数的转储,包括将其返回值解码为errno-设置。 ENTRY(syscall)只是表示该功能从那里开始。

L()ENTRY()是CPP宏。

L(pseudo_end)只是一个可以作为跳转目标的标签。也许SYSCALL_ERROR_LABEL的代码会跳回到那里,尽管这段代码只会更有效,因为它可能只是ret,所以也许它是来自旧版本的遗留物,或者用于其他目的。

+1

如果这是一个实际的指令,它的操作码是什么? – SasQ

+1

它是0x0F 0x05(只看英特尔的软件开发者手册)。 – flolo