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=Yesto 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 argumentBargumentB.
├────────┤
│ 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