This macrolibrary contains Unix | Linux kernel function invokation via interrupt 80h in 32bit mode.
INT 80x calling convention expects function identification in register EAX, and zero to six
function parameters in EBX, ECX, EDX, ESI, EDI, EBP, respectively.
Interrupt 0x80 on Linux always invokes the 32bit interface, regardless of what mode it is called from.
On 64bit system this will fail if the kernel was compiled without flag CONFIG_IA32_EMULATION.
Use syscall
instead.
.
Below you will find definition of symbolic function names, such as
exit, fork, read,,,
and two versions of macro which encapsulates the invokation of interrupt 0x80.
Macro names differ only in capitalization of their mnemonic:
Implementation int80 is fast but it does not keep the original contents of many registers and does not allow to use arbitrary register for parameter passing.
Implementation Int80 uses robust convention which preserves all registers except for EAX, which returns the function result.
User of robust variant does not have to keep on mind that function's parameter will be loaded to registers EBX, ECX, EDX etc, overwriting their previous contents. Parameters of Int80 can be provided in any GPR, e.g.Int80 write, stdout, ESI, ECX
.
And the robust variant is often shorter, because it loads registers withPUSH param ; POP reg
(2+1 bytes) instead ofMOV reg,param
(5 bytes).
The following example demonstrates both variants on function sys_mount
with five parameters:
int80 mount, =B"/dev/fda", =B"/mount/a", 0, FS_REQUIRES_DEV, NUL
|00000000: | ; Fast version.
|00000000: | int80 mount,=B"/dev/fda",=B"/mount/a",0,FS_REQUIRES_DEV,NUL
|00000000:BF00000000 + MOV EDI,NUL ; Load 5th parameter.
|00000005:BE04000000 + MOV ESI,FS_REQUIRES_DEV ; Load 4th parameter.
|0000000A:BA00000000 + MOV EDX,0 ; Load 3rd parameter.
|0000000F:B9[20000000] + MOV ECX,=B"mount/a" ; Load 2nd parameter.
|00000014:BB[29000000] + MOV EBX,=B"/dev/fda" ; Load 1st parameter.
|00000019:B815000000 + MOV EAX,mount ; Load function identification.
|0000001E:CD80 + INT 0x80 ; Invoke the system function.
|00000020: | ; Fast version (int80) occupies 32 bytes of code.
|00000000: | ; Robust version.
|00000000: | Int80 mount,=B"/dev/fda",=B"/mount/a",0,FS_REQUIRES_DEV,NUL
|00000000:60 + PUSHAD ; Save all registers.
|00000001:6A15 + PUSHD mount ; Function identification: mount.
|00000003:68[20000000] + PUSHD =B"/dev/fda" ; 1st parameter: device.
|00000008:68[29000000] + PUSHD =B"mount/a" ; 2nd parameter: directory.
|0000000D:6A00 + PUSHD 0 ; 3rd parameter: filesystem type.
|0000000F:6A04 + PUSHD FS_REQUIRES_DEV ; 4th parameter: mounting flags.
|00000011:6A00 + PUSHD NUL ; 5th parameter: pointer to data.
|00000013:5F + POP EDI ; Load 5th parameter.
|00000014:5E + POP ESI ; Load 4th parameter.
|00000015:5A + POP EDX ; Load 3rd parameter.
|00000016:59 + POP ECX ; Load 2nd parameter.
|00000017:5B + POP EBX ; Load 1st parameter.
|00000018:58 + POP EAX ; Load function identification.
|00000019:CD80 + INT 0x80 ; Invoke the system function.
|0000001B:8944241C + MOV [ESP+28],EAX ; Prepare returned value to [%ReturnEAX].
|0000001F:61 + POPAD ; Restore all registers but EAX.
|00000020: | ; Robust version (Int80) occupies 32 bytes of code.
lin80 HEAD
%Int80FnList %SET \ Declare syscall_name(number_of_parameters) restart_syscall(0),exit(1),fork(1),read(3),write(3),open(3),close(1),waitpid(3),creat(2),link(2), \ 0..9 unlink(1),execve(4),chdir(1),time(1),mknod(3),chmod(2),lchown16(3),17(0),stat(2),lseek(3), \ 10..19 getpid(0),mount(5),oldumount(1),setuid16(1),getuid16(0),stime(1),ptrace(4),alarm(1),fstat(2),pause(0), \ 20..29 utime(2),31(0),32(0),access(2),nice(1),35(0),sync(0),kill(2),rename(2),mkdir(2), \ 30..39 rmdir(1),dup(1),pipe(1),times(1),44(0),brk(1),setgid16(1),getgid16(0),signal(2),geteuid16(0), \ 40..69 getegid16(0),acct(1),umount(2),53(0),ioctl(3),fcntl(3),56(0),setpgid(2),58(0),olduname(1), \ 50..59 umask(1),chroot(1),ustat(2),dup2(2),getppid(0),getpgrp(0),setsid(0),sigaction(3),sgetmask(0),ssetmask(1), \ 60..69 setreuid16(2),setregid16(2),sigsuspend(3),sigpending(1),sethostname(2),setrlimit(2),old_getrlimit(2),getrusage(2),gettimeofday(2),settimeofday(2), \ 70..79 getgroups16(2),setgroups16(2),old_select(1),symlink(2),lstat(2),readlink(3),uselib(1),swapon(2),reboot(4),old_readdir(2), \ 80..89 old_mmap(1),munmap(2),truncate(2),ftruncate(2),fchmod(2),fchown16(3),getpriority(2),setpriority(3),98(0),statfs(2), \ 90..99 fstatfs(2),ioperm(3),socketcall(2),syslog(3),setitimer(3),getitimer(2),newstat(2),newlstat(2),newfstat(2),uname(1), \ 100..109 iopl(2),vhangup(0),111(0),vm86old(2),wait4(4),swapoff(1),sysinfo(1),ipc(0),fsync(1),sigreturn(1), \ 110..119 clone(5),setdomainname(2),newuname(1),modify_ldt(3),adjtimex(1),mprotect(3),sigprocmask(3),127(0),init_module(3),delete_module(2), \ 120..129 130(0),quotactl(4),getpgid(1),fchdir(1),bdflush(2),sysfs(3),personality(1),137(0),setfsuid16(1),setfsgid16(1), \ 130..139 llseek(5),getdents(3),select(5),flock(2),msync(3),readv(3),writev(3),getsid(1),fdatasync(1),sysctl(1), \ 140..149 mlock(2),munlock(2),mlockall(1),munlockall(0),sched_setparam(2),sched_getparam(2),sched_setscheduler(3),sched_getscheduler(1),sched_yield(0),sched_get_priority_max(1), \ 150..159 sched_get_priority_min(1),sched_rr_get_interval(2),nanosleep(2),mremap(5),setresuid16(3),getresuid16(3),vm86(3),167(0),poll(3),nfsservctl(3), \ 160..169 setresgid16(3),getresgid16(3),prctl(5),rt_sigreturn(1),sigaction(4),sigprocmask(4),sigpending(2),sigtimedwait(4),sigqueueinfo(3),sigsuspend(2), \ 170..179 pread64(4),pwrite64(4),chown16(3),getcwd(2),capget(2),capset(2),sigaltstack(3),sendfile(4),188(0),189(0), \ 180..189 vfork(1),getrlimit(2),nmap_pgoff(0),truncate64(2),ftruncate64(2),stat64(2),lstat64(2),fstat64(2),lchown(3),getuid(0), \ 190..199 getgid(0),geteuid(0),getegid(0),setreuid(2),setregid(2),getgroups(2),setgroups(2),fchown(3),setresuid(3),getresuid(3), \ 200..209 setresgid(3),getresgid(3),chown(3),setuid(1),setgid(1),setfsuid(1),setfsgid(1),pivot_root(2),mincore(3),madvise(3), \ 210..219 getdents64(3),fcntl64(3),222(0),223(0),gettid(0),readahead(3),setxattr(5),lsetxattr(5),fsetxattr(5),getxattr(4), \ 220..229 lgetxattr(4),fgetxattr(4),listxattr(3),llistxattr(3),flistxattr(3),removexattr(2),lremovexattr(2),fremovexattr(2),tkill(2),sendfile64(4), \ 230..239 futex(0),sched_setaffinity(3),sched_getaffinity(3),set_thread_area(1),get_thread_area(1),io_setup(2),io_destroy(1),io_getevents(5),io_submit(3),io_cancel(3), \ 240..249 fadvise64(4),251(0),exit_group(1),lookup_dcookie(3),epoll_create(1),epoll_ctl(4),epoll_wait(4),remap_file_pages(5),set_tid_address(1),timer_create(3), \ 250..259 timer_settime(4),timer_gettime(2),timer_getoverrun(1),timer_delete(1),clock_settime(2),clock_gettime(2),clock_getres(2),clock_nanosleep(4),statfs64(3),fstatfs64(2), \ 260..269 tgkill(3),utimes(2),fadvise64_64(4),273(0),mbind(0),get_mempolicy(5),set_mempolicy(3),mq_open(4),mq_unlink(1),mq_timedsend(5), \ 270..279 mq_timedreceive(5),mq_notify(2),mq_getsetattr(3),kexec_load(4),waitid(5),285(0),add_ket(5),request)key(4),keyctl(5),ioprio_set(3), \ 280..289 ioprio_get(2),inotify_init(0),inotify_add_watch(3),inotify_rm_watch(2),migrate_pages(4),openat(4),mkdirat(4),mknodat(4),fchownat(5),futimesat(3), \ 290..299 fstatat64(4),unlinkat(3),renameat(4),linkat(5),symlinkat(3),readlinkat(4),fchmodat(3),faccessat(3),pselect6(0),ppoll(5), \ 300..309 unshare(1),set_robust_list(2),get_robust_list(3),splice(0),sync_file_range(4),tee(4),vmsplice(4),move_pages(0),getcpu(3),epoll_pwait(0), \ 310..319 utimensat(4),signalfd(3),timerfd_create(2),eventfd(1),fallocate(4),timerfd_settime(4),timerfd_gettime(2),signalfd4(3),eventfd2(2),epoll_create1(1), \ 320..329 dup3(3),pipe2(2),inotify_init1(1),preadv(5),pwritev(5),rt_tgsigqueueinfo(4),perf_event_open(5),recvmmsg(5) ; 330..337
int80 %MACRO Name, Par1, Par2,,,, %IF "%Name" === "" %ERROR ID=5810,Macro "%0" requires function name and parameters. %EXITMACRO int80 %ENDIF %GPR %SET EBX,ECX,EDX,ESI,EDI,EBP %FnNr %SETA 0 FnRef %FOR %Int80FnList ; Enumerate kernel function declarations. %IF "%Name" == "%FnRef[1..%&-3]" ; Omit the last three characters from function declaration. %ParNr %SETA %FnRef[%&-1] ; Pick-up the digit from parenthesis. %IF %ParNr <> %# - 1 %ERROR ID=5811,Macro "%0 %Name" requires %ParNr parameter(s). %EXITMACRO int80 %ENDIF %WHILE %ParNr > 0 %ParType %SETA TYPE# %*{%ParNr+1} %IF %ParType != 'R' MOV %GPR{%ParNr},%*{%ParNr+1} ; Copy immediate or pointer parameter to GPR. %ELSE ; Parametr is provided in a register. %IF "%GPR{%ParNr}" !== "%*{%ParNr+1}" ; Skip if its already there. MOV %GPR{%ParNr},%*{%ParNr+1} ; Copy register parameter to GPR. %ENDIF %ENDIF %ParNr %SETA %ParNr-1 ; Repeat with the previous parameter. %ENDWHILE MOV EAX,%FnNr ; Load function's identification number. INT 0x80 ; Perform the system call. %EXITMACRO int80 ; Stop further search in %Int80FnList. %ENDIF %FnNr %SETA %FnNr+1 ; Try the next function reference. %ENDFOR FnRef %ERROR ID=5812,Unrecognized function name "%Name". See %%Int80FnList in "%^SourceFile". %ENDMACRO int80
Int80 %MACRO Name, Par1, Par2,,,, %IF "%Name" === "" %ERROR ID=5810,Macro "%0" requires function name and parameters. %EXITMACRO Int80 %ENDIF %GPR %SET EBX,ECX,EDX,ESI,EDI,EBP %FnNr %SETA 0 FnRef %FOR %Int80FnList ; Enumerate kernel function declarations. found %IF "%Name" == "%FnRef[1..%&-3]" ; Omit the last three characters from function declaration. %ParNr %SETA %FnRef[%&-1] ; Pick-up the digit from parenthesis. %IF %ParNr <> %# - 1 %ERROR ID=5811,Macro "%0 %Name" requires %ParNr parameter(s). %EXITMACRO Int80 %ENDIF PUSHAD PUSHD %FnNr %IF %# > 1 PUSHD %*{2..} ; Push all parameters on stack in nominal order. %WHILE %ParNr > 0 POP %GPR{%ParNr} ; Pop all parameters from stack in reversed order. %ParNr %SETA %ParNr-1 %ENDWHILE %ENDIF POP EAX ; Pop function identification number. INT 0x80 ; Perform the system call. MOV [ESP+28],EAX ; Copy the result to [%ReturnEAX]. POPAD ; Restore all registers but EAX. %EXITMACRO Int80 ; Stop further search in %Int80FnList. %ENDIF found %FnNr %SETA %FnNr+1 %ENDFOR FnRef %ERROR ID=5812,Unrecognized function name "%Name". See %%Int80FnList in "%^SourceFile". %ENDMACRO Int80
ENDHEAD lin80