Assembly Syscall Question
John Baldwin
jhb at FreeBSD.org
Mon Aug 4 12:14:47 PDT 2003
On 31-Jul-2003 Ryan Sommers wrote:
> When making a system call to the kernel why is it necessary to push the
> syscall value onto the stack when you don't call another function?
>
> Example:
>
> access.the.bsd.kernel:
> int 80h
> ret
>
> func:
> mov eax, 4 ; Write
> call access.the.bsd.kernel
> ; End
>
> Works. However:
> func:
> mov eax, 4 ; Write
> int 80h
> ; End
>
> Doesn't.
>
> Now, if you change it to:
>
> func:
> mov eax, 4 ; Write
> push eax
> int 80h
> ; End
>
> It does work. I was able to find, "By default, the FreeBSD kernel uses the C
> calling convention. Further, although the kernel is accessed using int 80h,
> it is assumed the program will call a function that issues int 80h, rather
> than issuing int 80h directly," in the developer's handbook. But I can't
> figure out why the second example doesn't work. Is the call instruction
> pushing the value onto the stack in addition to pushing the instruction
> pointer on?
>
> Thank you in advance.
> PS I'm not on the list.
First off, why are you using asm for userland stuff? Secondly, the kernel
assumes that all the other arguments besides the syscall to execute (i.e.
%eax) are passed on the user stack. Thus, it has to have a set location
relative to the user stack pointer to find the arguments. It allows for
a return IP from a call instruction to be at the top of the stack. You
can tell this by looking at syscall() in sys/i386/i386/trap.c:
params = (caddr_t)frame.tf_esp + sizeof(int);
code = frame.tf_eax;
orig_tf_eflags = frame.tf_eflags;
params is a userland pointer to the function arguments. Adding the
sizeof(int) skips over the saved return address, or in your 3rd case,
the dummy %eax value.
--
John Baldwin <jhb at FreeBSD.org> <>< http://www.FreeBSD.org/~jhb/
"Power Users Use the Power to Serve!" - http://www.FreeBSD.org/
More information about the freebsd-hackers
mailing list