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