|
楼主 |
发表于 2003-6-24 23:21:15
|
显示全部楼层
★6.2 用汇编语言编程
假如我们在系统调用时需要传5个参数时候,内嵌的汇编代码即使是PIC
的,也不能工作,因为x86没有足够的寄存器。我们需要直接用汇编语言
编写。
syscall(int syscall_number,...)的一般汇编代码如下:
.file "syscall.S"
.text
.global syscall
.global errno
.align 16
syscall:
pushl 5ebp
movl %esp,%ebp
pushl %edi
pushl %esi
pushl %ebx
movl 8(%ebp),%eax
movl 12(%ebp),%ebx
movl 16(%ebp),%ecx
movl 20(%ebp),%edx
movl 24(%ebp),%esi
movl 28(%ebp),%edi
int $0x80
test %eax,%eax
jpe .LLexit
negl %eax
movl %eax,errno
movl $-1, %eax
.LLexit:
popl %ebx
popl %esi
popl %edi
movl %ebp,%esp
popl %ebp
ret
.type syscall,@function
.L_syscall_end:
.size syscall,.L_syscall_end -syscall
在PIC下,我们必须通过GOT(global offset table)来访问任何全局变量
(除了保存在基寄存器ebx中的)。修改的代码如下:
.file "syscall.S"
.text
.global syscall
.global errno
.align 16
syscall:
pushl %ebp
movl %esp,%ebp
pushl %edi
pushl %esi
pushl %ebx
call .LL4
.LL4:
popl %ebx
addl $_GLOBAL_OFFSET_TABLE_+[.- .LL4],%ebx
pushl %ebx
movl 8(%ebp),%eax
movl 12(%ebp),%ebx
movl 16(%ebp),%ecx
movl 20(%ebp),%edx
movl 24(%ebp),%esi
movl 28(%ebp),%edi
int $0x80
popl %ebx
movl %eax,%edx
test %edx,%edx
jge .LLexit
negl %edx
movl errno@GOT(%ebx),%eax
movl %edx,(%eax)
movl $-1,%eax
.LLexit:
popl %ebx
popl %esi
popl %edi
movl %ebp,%esp
popl %ebp
ret
.type syscall,@function
.L_syscall_end:
.size syscall,.L_syscall_end-syscall
假如要得到PIC的汇编代码,但是又不知道如何写,你可以写一个C的,然后如下
编译:
#gcc -O -fPIC -S foo.c
它将告诉gcc产生汇编代码foo.s输出,根据需要,可以修改它。 |
|