This file can be included to 32bit Linux programs written in EuroAssembler.
It declares macroinstructions for interaction with
Linux kernel 32bit Application Programming Interface which uses
INT 0x80
to invoke core function of operating system.
Access method INT 0x80
always invokes the 32bit interface,
regardless if it is called from 32bit or 64bit mode.
On 64bit system this will fail if the kernel was compiled without flag CONFIG_IA32_EMULATION.
Function arguments %1..%6 are transferred in registers EBX,ECX,EDX,ESI,EDI,EBP
, respectively.
EAX
contains the function's ordinal number 0..337 from the list
%LinSyscall32List.
linapi HEAD
%LinSyscall32List %SET \ Declare 32bit syscall_name(number_of_parameters). restart_syscall(0),exit(1),fork(1),read(3),write(3), \ 000..004 open(3),close(1),waitpid(3),creat(2),link(2), \ 005..009 unlink(1),execve(4),chdir(1),time(1),mknod(3), \ 010..014 chmod(2),lchown16(3),17(0),stat(2),lseek(3), \ 015..019 getpid(0),mount(5),oldumount(1),setuid16(1),getuid16(0), \ 020..024 stime(1),ptrace(4),alarm(1),fstat(2),pause(0), \ 025..029 utime(2),31(0),32(0),access(2),nice(1), \ 030..034 35(0),sync(0),kill(2),rename(2),mkdir(2), \ 035..039 rmdir(1),dup(1),pipe(1),times(1),44(0), \ 040..044 brk(1),setgid16(1),getgid16(0),signal(2),geteuid16(0), \ 045..049 getegid16(0),acct(1),umount(2),53(0),ioctl(3), \ 050..054 fcntl(3),56(0),setpgid(2),58(0),olduname(1), \ 055..059 umask(1),chroot(1),ustat(2),dup2(2),getppid(0), \ 060..064 getpgrp(0),setsid(0),sigaction(3),sgetmask(0),ssetmask(1), \ 065..069 setreuid16(2),setregid16(2),sigsuspend(3),sigpending(1),sethostname(2), \ 070..074 setrlimit(2),old_getrlimit(2),getrusage(2),gettimeofday(2),settimeofday(2), \ 075..079 getgroups16(2),setgroups16(2),old_select(1),symlink(2),lstat(2), \ 080..084 readlink(3),uselib(1),swapon(2),reboot(4),old_readdir(2), \ 085..089 old_mmap(1),munmap(2),truncate(2),ftruncate(2),fchmod(2), \ 090..094 fchown16(3),getpriority(2),setpriority(3),98(0),statfs(2), \ 095..099 fstatfs(2),ioperm(3),socketcall(2),syslog(3),setitimer(3), \ 100..104 getitimer(2),newstat(2),newlstat(2),newfstat(2),uname(1), \ 105..109 iopl(2),vhangup(0),111(0),vm86old(2),wait4(4), \ 110..114 swapoff(1),sysinfo(1),ipc(0),fsync(1),sigreturn(1), \ 115..119 clone(5),setdomainname(2),newuname(1),modify_ldt(3),adjtimex(1), \ 120..124 mprotect(3),sigprocmask(3),127(0),init_module(3),delete_module(2), \ 125..129 130(0),quotactl(4),getpgid(1),fchdir(1),bdflush(2), \ 130..134 sysfs(3),personality(1),137(0),setfsuid16(1),setfsgid16(1), \ 135..139 llseek(5),getdents(3),select(5),flock(2),msync(3), \ 140..144 readv(3),writev(3),getsid(1),fdatasync(1),sysctl(1), \ 145..149 mlock(2),munlock(2),mlockall(1),munlockall(0),sched_setparam(2), \ 150..154 sched_getparam(2),sched_setscheduler(3),sched_getscheduler(1), \ 155..157 sched_yield(0),sched_get_priority_max(1), \ 158..159 sched_get_priority_min(1),sched_rr_get_interval(2),nanosleep(2),mremap(5), \ 160..163 setresuid16(3),getresuid16(3),vm86(3),167(0),poll(3),nfsservctl(3), \ 164..169 setresgid16(3),getresgid16(3),prctl(5),rt_sigreturn(1),sigaction(4), \ 170..174 sigprocmask(4),sigpending(2),sigtimedwait(4),sigqueueinfo(3),sigsuspend(2), \ 175..179 pread64(4),pwrite64(4),chown16(3),getcwd(2),capget(2), \ 180..184 capset(2),sigaltstack(3),sendfile(4),188(0),189(0), \ 185..189 vfork(1),getrlimit(2),nmap_pgoff(0),truncate64(2),ftruncate64(2), \ 190..194 stat64(2),lstat64(2),fstat64(2),lchown(3),getuid(0), \ 195..199 getgid(0),geteuid(0),getegid(0),setreuid(2),setregid(2), \ 200..204 getgroups(2),setgroups(2),fchown(3),setresuid(3),getresuid(3), \ 205..209 setresgid(3),getresgid(3),chown(3),setuid(1),setgid(1), \ 210..214 setfsuid(1),setfsgid(1),pivot_root(2),mincore(3),madvise(3), \ 215..219 getdents64(3),fcntl64(3),222(0),223(0),gettid(0), \ 220..224 readahead(3),setxattr(5),lsetxattr(5),fsetxattr(5),getxattr(4), \ 225..229 lgetxattr(4),fgetxattr(4),listxattr(3),llistxattr(3),flistxattr(3), \ 230..234 removexattr(2),lremovexattr(2),fremovexattr(2),tkill(2),sendfile64(4), \ 235..239 futex(0),sched_setaffinity(3),sched_getaffinity(3),set_thread_area(1), \ 240..243 get_thread_area(1),io_setup(2),io_destroy(1),io_getevents(5),io_submit(3), \ 244..248 io_cancel(3),fadvise64(4),251(0),exit_group(1),lookup_dcookie(3), \ 249..253 epoll_create(1), epoll_ctl(4),epoll_wait(4),remap_file_pages(5), \ 254..257 set_tid_address(1),timer_create(3),timer_settime(4),timer_gettime(2), \ 258..261 timer_getoverrun(1),timer_delete(1),clock_settime(2),clock_gettime(2), \ 262..265 clock_getres(2),clock_nanosleep(4),statfs64(3),fstatfs64(2), \ 266..269 tgkill(3),utimes(2),fadvise64_64(4),273(0),mbind(0), \ 270..274 get_mempolicy(5),set_mempolicy(3),mq_open(4),mq_unlink(1),mq_timedsend(5), \ 275..279 mq_timedreceive(5),mq_notify(2),mq_getsetattr(3),kexec_load(4),waitid(5), \ 280..284 285(0),add_ket(5),request)key(4),keyctl(5),ioprio_set(3), \ 285..289 ioprio_get(2),inotify_init(0),inotify_add_watch(3),inotify_rm_watch(2), \ 290..293 migrate_pages(4),openat(4),mkdirat(4),mknodat(4),fchownat(5),futimesat(3), \ 294..299 fstatat64(4),unlinkat(3),renameat(4),linkat(5),symlinkat(3), \ 300..304 readlinkat(4),fchmodat(3),faccessat(3),pselect6(0),ppoll(5), \ 305..309 unshare(1),set_robust_list(2),get_robust_list(3),splice(0), \ 310..313 sync_file_range(4),tee(4),vmsplice(4),move_pages(0),getcpu(3), \ 314..318 epoll_pwait(0),utimensat(4),signalfd(3),timerfd_create(2),eventfd(1), \ 319..323 fallocate(4),timerfd_settime(4),timerfd_gettime(2),signalfd4(3), \ 324..327 eventfd2(2),epoll_create1(1),dup3(3),pipe2(2),inotify_init1(1),preadv(5), \ 328..333 pwritev(5),rt_tgsigqueueinfo(4),perf_event_open(5),recvmmsg(5), \ 334..337 ;
This macroinstruction encapsulates invokation of Linux 32bit kernel functions
using machine instruction INT 0x80
.
exit
, fork
, read
etc (case insensitive).
Its ordinal number will be provided in register EAX.
When you want to use the fast (nondefault) mode in all LinAPI invokations, you don't have to append,Fastmode=Yes
to every invokation of this macro if you set preprocessing %variable in the beginning of the program:%Fastmode %SETB Yes
.
User of default robust mode (Fastmode=off
) does not have to keep on mind that function's parameter will be loaded
to registers EBX, ECX, EDX etc, overwriting their previous contents.
Arguments of macro may be provided in any 32bit GPR, e.g.
LinAPI write, STDOUT_FILENO, ESI, ECX
.
And the robust variant is often shorter, because it loads registers with PUSH param ; POP reg
(2+1 bytes) instead of MOV reg,param
(5 bytes).
The following example demonstrates both modes of LinAPI invoking the function
mount with five arguments:
LinAPI mount, =B"/dev/fda", =B"/mount/a", 0, MS_RDONLY, NUL
|00000000: | ; Fast version.
|00000000: | LinAPI mount,=B"/dev/fda",=B"/mount/a",0,MS_RDONLY,NUL, Fastmode=Yes
|00000000:BF00000000 + MOV EDI,NUL ; Load 5th parameter: pointer to data.
|00000005:BE01000000 + MOV ESI,MS_RDONLY ; Load 4th parameter: mounting flags.
|0000000A:BA00000000 + MOV EDX,0 ; Load 3rd parameter: filesystem type.
|0000000F:B9[20000000] + MOV ECX,=B"mount/a" ; Load 2nd parameter: directory.
|00000014:BB[29000000] + MOV EBX,=B"/dev/fda" ; Load 1st parameter: device.
|00000019:B815000000 + MOV EAX,mount ; Load function identification.
|0000001E:CD80 + INT 0x80 ; Invoke the system function.
|00000020: | ; LinAPI in fast mode occupies 32 bytes of code.
|00000000: | ; Robust version.
|00000000: | LinAPI mount,=B"/dev/fda",=B"/mount/a",0,MS_RDONLY,NUL, Fastmode=No
|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:6A01 + PUSHD MS_RDONLY ; 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: | ; LinAPI in robust mode occupies 32 bytes of code.
LinAPI %MACRO Sys_call, Arg1,Arg2,Arg3,Arg4,Arg5,Arg6, Fastmode=%Fastmode %GPR %SET EBX,ECX,EDX,ESI,EDI,EBP ; Enumerate registers for transfer of arguments. %FnNr %SETA 0 ; Function identification 0..337, transferred in EAX. FnRef %FOR %LinSyscall32List ; Walk thru kernel function declarations. found %IF "%Sys_call" == "%FnRef[1..%&-3]" ; Omit the last three characters from function reference declaration and compare. %ArgC %SETA %FnRef[%&-1] ; Sys_call name was found. Pick up the digit from parenthesis ('0'..'6'). checkArg %IF %ArgC <> %# - 1 %ERROR ID=5811,Macro "%0 %Sys_call" requires %ArgC arguments. %EXITMACRO LinAPI %ENDIF checkArg mode %IF %Fastmode ; Fast mode. params %WHILE %ArgC > 0 %IF "%GPR{%ArgC}" !== "%*{%ArgC+1}" ; Skip if the argument already is in transfer register. MOV %GPR{%ArgC},%*{%ArgC+1} ; otherwise copy the parameter to GPR. %ENDIF %ArgC %SETA %ArgC-1 ; Repeat with the previous parameter. %ENDWHILE params MOV EAX,%FnNr ; Load Sys_call's identification number. INT 0x80 ; Perform the kernel call. %EXITMACRO LinAPI ; Stop further search in %LinSyscall32List. %ELSE mode ; Robust mode. PUSHAD ; Save all registers. PUSHD %FnNr ; Push Function's identificator (0..337). atleast1 %IF %# > 1 ; If the Function expects more then 0 parameters. PUSHD %*{2..} ; Push all arguments on stack in nominal order. popPars %WHILE %ArgC > 0 POP %GPR{%ArgC} ; Pop all arguments from stack to their transfer registers. %ArgC %SETA %ArgC-1 ; Arguments are popped in reversed order. %ENDWHILE popPars %ENDIF atleast1 POP EAX ; Load function identification number %FnNr to EAX. INT 0x80 ; Perform the kernel call. MOV [ESP+28],EAX ; Copy the Function result to [%ReturnEAX]. POPAD ; Restore all registers with updated EAX and EFlags. %EXITMACRO LinAPI ; Stop further search in %LinSyscall32List. %ENDIF mode %ENDIF found ; Otherwise continue search. %FnNr %SETA %FnNr+1 ; Try the next function reference in %LinSyscall32List. %ENDFOR FnRef %ERROR ID=5812,Unrecognized syscall name "%Sys_call". See %%LinSyscall32List in "linapi.htm". %ENDMACRO LinAPI
argc
value.
Frame=ESP
is valid only if nothing has been pushed yet
since the program started. Otherwise use something like Frame=ESP+4
,
Frame=EBP+12
etc.executable
launched from console as
./executable --option argumentA argumentB
argumentB
.
├────────┤
│ argv2 │ Pointer to ASCIIZ string argumentA
.
├────────┤
│ argv1 │ Pointer to ASCIIZ string --option
.
├────────┤
│ execut │ Pointer to this executable file name ./executable
.
├────────┤
│ argc │ Number of arguments including the executable itself 4
.
Frame-> └────────┘
GetArg %MACRO ArgNumber, Frame=ESP LEA ECX,[%Frame] PUSHD ECX, %ArgNumber CALL GetArgLin32@RT GetArgLin32@RT:: PROC1 ; Stdcalled with %Param1=ArgNumber, Param2=Frame. PUSHAD MOV EBP,ESP MOV ESI,[%Param2] ; Frame. MOV EBX,[%Param1] ; Requested ArgNumber (0..126) or -1. SUB EDX,EDX MOV ECX,[ESI] ; argc (1..127). CMP EBX,-1 ; Test if GetArg was invoked from GetArgCount. JNE .50: DEC ECX ; Do not count the executable itself. JMP .80: .Error:STC JMP .80: .50: CMP EBX,126 JA .Error: CMP ECX,EDX JZ .Error: ; Invalid argc, bad %Frame provided. CMP ECX,127 JA .Error: CMP EBX,ECX JNB .Error: ; This many arguments are not available. MOV EDI,[ESI+4*EBX+4] TEST EDI JZ .Error: ; Invalid %Frame. MOV [%ReturnESI],EDI XOR ECX,ECX DEC ECX REPNE SCASB ; Find the zero terminator, set CF=0. NOT ECX DEC ECX .80: MOV [%ReturnECX],ECX ; Argument size without the terminating zero. .90:POPAD RET 2*4 ENDP1 GetArgLin32@RT %ENDMACRO GetArg
argc
value.
Frame=ESP
is valid only if nothing has been pushed yet
since the program started. Otherwise use something like Frame=ESP+4
,
Frame=EBP+12
etc.GetArgCount %MACRO Frame=ESP GetArg -1, Frame=%Frame %ENDMACRO GetArgCount
Macro StdOutput writes one or more concatenated strings to the standard output or to other device or file specified with the Handle identifier.
Strings are either zero-terminated, or the keyword Size= must specify their size in bytes. The terminating NUL character is never written to output.
If keyword Eol=Yes, macro writes LF=0x0A after all strings.
LF
(0x10) will be written on output after all strings have been written.
StdOutput %MACRO String1,String2,,,Size=-1, Handle=1, Eol=No OpNr %FOR 1..%#, STEP=1 ; Walk through all ordinal operands. PUSHD %Handle, %Size, %1 CALL StdOutputLin32@RT %SHIFT 1 ; The next string to write. %ENDFOR OpNr eol %IF %Eol PUSHD %Handle, 1, 0 ; NUL string pointer is the request for LF. CALL StdOutputLin32@RT %ENDIF eol StdOutputLin32@RT:: PROC1 PUSHAD PUSHD 0x0A ; Prepare Eol character on stack. MOV EBX,[ESP+48] ; File descriptor %Handle. MOV ECX,[ESP+44] ; String maximal %Size. MOV EDI,[ESP+40] ; String pointer or 0 for Eol. XOR EAX,EAX CMP EDI,EAX JNZ .10: ; NULL pointer signalizes Eol request. INC EDI ; Size of Eol=1. MOV ESI,ESP ; Pointer to Eol (0x0A). JMP .50: .10: MOV ESI,EDI REPNE SCASB ; Find the end of string. JNE .30: DEC EDI ; Skip the NUL terminator. .30: SUB EDI,ESI ; Netto string is now ESI,EDI .50: LinAPI write,EBX,ESI,EDI, Fastmode=Yes SAL EAX ; Copy SF to CF (this signalizes an error). .90: POP EAX POPAD RET 3*4 ENDP1 StdOutputLin32@RT:: %ENDMACRO StdOutput
Macro StdInput reads from standard input specified by the Handle.
StdInput %MACRO Buffer, Size=, Handle=0 %IF "%Size" === "" PUSHD SIZE# %Buffer, %Buffer, %Handle %ELSE PUSHD %Size, %Buffer, %Handle %ENDIF CALL StdInputLin32@RT StdInputLin32@RT::PROC1 ; StdCalled with params Handle, BufferPtr, BufferSize. PUSHAD MOV EBP,ESP LinAPI read,[%Param1],[%Param2],[%Param3], Fastmode=On MOV [%ReturnECX],EAX SAL EAX ; Copy SF to CF (this signalizes an error). .90:POPAD RET 3*4 ENDPROC1 StdInputLin32@RT:: %ENDMACRO StdInput
Errorlevel=
, this value may also be specified as an ordinal operand.
TerminateProgram %MACRO Errorlevel=0 %IF %#=1 ; If ordinal operand was provided. PUSHD %1 %ELSE PUSHD %Errorlevel ; If keyword operand was provided. %ENDIF POP EBX LinAPI exit,EBX, Fastmode=On %ENDMACRO TerminateProgram
ENDHEAD linapi