我想知道在 Linux 下在 x86 汇编器中执行系统调用的不同方法是什么。但是,没有作弊,只能使用汇编程序(即编译gcc必须使用
-nostdlib)。
我知道四种执行系统调用的方法,即:
int $0x80sysenter(i586)call *%gs:0x10(vdso 蹦床)syscall(amd64)
我很擅长使用int $0x80,例如,这里有一个经典的“Hello World!”的示例代码。在汇编程序中使用int $0x80(用 编译gcc -nostdlib -o hello-int80 hello-int80.s):
.data
msg:
  .ascii "Hello World!\n"
  len = . - msg
.text
.globl _start
_start:
# Write the string to stdout
  movl  $len, %edx
  movl  $msg, %ecx
  movl  $1, %ebx
  movl  $4, %eax
  int   $0x80
# and exit
  movl  $0, %ebx
  movl  $1, %eax
  int   $0x80
但sysenter通常以分段错误错误结束。为什么 ?而且,如何正确使用它?
这是一个带有call *%gs:0x10(用 编译gcc -o hello-gs10 hello-gs10.s)的示例。请注意,libc在正确调用它之前,我需要进行初始化(这就是我使用main而不是再使用的原因_start,这也是我-nostdlib从编译行中删除该选项的原因):
.data
msg:
  .ascii "Hello World!\n"
  len = . - msg
.text
.globl main
main:
# Write the string to stdout
  movl  $len, %edx
  movl  $msg, %ecx
  movl  $1, %ebx
  movl  $4, %eax
  call  *%gs:0x10
# and exit
  movl  $0, %ebx
  movl  $1, %eax
  call  *%gs:0x10
此外,syscall如果您知道此架构的系统调用代码(感谢 lfxgroove)(编译为:),它也能正常工作gcc -m64 -nostdlib -o hello-syscall hello-syscall.s:
.data
msg:
  .ascii "Hello World!\n"
  len = . - msg
.text
.globl _start
_start:
# Write the string to stdout
  movq  $len, %rdx
  movq  $msg, %rsi
  movq  $1, %rdi
  movq  $1, %rax
  syscall
# and exit
  movq  $0, %rdi
  movq  $60, %rax
  syscall
因此,我必须以这种sysenter方式触发系统调用的唯一问题。这是一个sysenter以分段错误结尾的示例(编译为gcc -m32 -nostdlib -o hello-sysenter hello-sysenter.s):
.data
msg:
  .ascii "Hello World!\n"
  len = . - msg
.text
.globl _start
_start:
# Write the string to stdout
  movl  $len, %edx
  movl  $msg, %ecx
  movl  $1, %ebx
  movl  $4, %eax
  push    final
  sub $12, %esp
  mov %esp, %ebp
  sysenter
# and exit
final:  
  movl  $0, %ebx
  movl  $1, %eax
  sub $12, %esp
  mov %esp, %ebp
  sysenter