Раздел «Язык Ассемблера».LinuxSyscalls:

Системные вызовы в Linux

Syscalls.

This section will outline the use of linux syscalls in assembly language. Syscalls consist of all the functions in the second section of the manual pages located in /usr/man/man2. They are also listed in: /usr/include/sys/syscall.h. A great list is at http://www.linuxassembly.org/syscall.html. These functions can be executed via the linux interrupt service: int $0x80. Syscalls with < 6 args.

For all syscalls, the syscall number goes in %eax. For syscalls that have less than six args, the args go in %ebx,%ecx,%edx,%esi,%edi in order. The return value of the syscall is stored in %eax.

The syscall number can be found in /usr/include/sys/syscall.h. The macros are defined as SYS_ i.e. SYS_exit, SYS_close, etc.

Example: (Hello world program - it had to be done)

According to the write(2) man page, write is declared as: ssize_t write(int fd, const void *buf, size_t count);

Hence fd goes in %ebx, buf goes in %ecx, count goes in %edx and SYS_write goes in %eax. This is followed by an int $0x80 which executes the syscall. The return value of the syscall is stored in %eax.

$ cat write.s
.include "defines.h"
.data
hello:
        .string "hello world\n"

.globl  main
main:
        movl    $SYS_write,%eax
        movl    $STDOUT,%ebx
        movl    $hello,%ecx
        movl    $12,%edx
        int     $0x80

        ret

The same process applies to syscalls which have less than five args. Just leave the un-used registers unchanged. Syscalls such as open or fcntl which have an optional extra arg will know what to use. Syscalls with > 5 args.

Syscalls whos number of args is greater than five still expect the syscall number to be in %eax, but the args are arranged in memory and the pointer to the first arg is stored in %ebx.

If you are using the stack, args must be pushed onto it backwards, i.e. from the last arg to the first arg. Then the stack pointer should be copied to %ebx. Otherwise copy args to an allocated area of memory and store the address of the first arg in %ebx. Example: (mmap being the example syscall). Using mmap() in C:

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

#define STDOUT  1

int main(void) {
        char file[]="mmap.s";
        char *mappedptr;
        int fd,filelen;

        fd=fopen(file, O_RDONLY);
        filelen=lseek(fd,0,SEEK_END);
        mappedptr=mmap(NULL,filelen,PROT_READ,MAP_SHARED,fd,0);
        write(STDOUT, mappedptr, filelen);
        munmap(mappedptr, filelen);
        close(fd);
        return 0;
}

Arrangement of mmap() args in memory:

%esp            %esp+4          %esp+8          %esp+12         %esp+16 %esp+20
00000000        filelen         00000001        00000001        fd      00000000

ASM Equivalent:

$ cat mmap.s
.include "defines.h"

.data
file:
        .string "mmap.s"
fd:
        .long   0
filelen:
        .long   0
mappedptr:
        .long   0

.globl main
main:
        push    %ebp
        movl    %esp,%ebp
        subl    $24,%esp

//      open($file, $O_RDONLY);

        movl    $fd,%ebx        // save fd
        movl    %eax,(%ebx)

//      lseek($fd,0,$SEEK_END);

        movl    $filelen,%ebx   // save file length
        movl    %eax,(%ebx)

        xorl    %edx,%edx

//      mmap(NULL,$filelen,PROT_READ,MAP_SHARED,$fd,0);
        movl    %edx,(%esp)
        movl    %eax,4(%esp)    // file length still in %eax
        movl    $PROT_READ,8(%esp)
        movl    $MAP_SHARED,12(%esp)
        movl    $fd,%ebx        // load file descriptor
        movl    (%ebx),%eax
        movl    %eax,16(%esp)
        movl    %edx,20(%esp)
        movl    $SYS_mmap,%eax
        movl    %esp,%ebx
        int     $0x80

        movl    $mappedptr,%ebx // save ptr
        movl    %eax,(%ebx)
                
//      write($stdout, $mappedptr, $filelen);
//      munmap($mappedptr, $filelen);
//      close($fd);
        
        movl    %ebp,%esp
        popl    %ebp

        ret
$

NOTE: The above source listing differs from the example source code found at the end of the article. The code listed above does not show the other syscalls, as they are not the focus of this section. The source above also only opens mmap.s, whereas the example source reads the command line arguments. The mmap example also uses lseek to get the filesize.

Attachment sort Action Size Date Who Comment
syscall.html manage 30.5 K 02 Mar 2005 - 21:42 ArtemVoroztsov Linux syscalls descriptions