我想知道在 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