我想知道在 Linux 下在 x86 汇编器中执行系统调用的不同方法是什么。但是,没有作弊,只能使用汇编程序(即编译gcc
必须使用
-nostdlib
)。
我知道四种执行系统调用的方法,即:
int $0x80
sysenter
(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