有的系统调用会返回复杂的C类型的数据结构,下面就介绍如何在汇编里使用这种类型的系统调用...
NAME
sysinfo - returns information on overall system statistics
SYNOPSIS
#include <sys/sysinfo.h>
int sysinfo(struct sysinfo *info);
..........................................
..........................................
|
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding for libc5 */
};
|
|
.section .data result: uptime: .int 0 load1: .int 0 load5: .int 0 load15: .int 0 totalram: .int 0 freeram: .int 0 sharedram: .int 0 bufferram: .int 0 totalswap: .int 0 freeswap: .int 0 procs: .byte 0x00, 0x00 totalhigh: .int 0 freehigh: .int 0 memunit: .int 0 |
|
# sysinfo.s - Retrieving system information via kernel system calls .section .data result: uptime: .int 0 load1: .int 0 load5: .int 0 load15: .int 0 totalram: .int 0 freeram: .int 0 sharedram: .int 0 bufferram: .int 0 totalswap: .int 0 freeswap: .int 0 procs: .byte 0x00, 0x00 totalhigh: .int 0 freehigh: .int 0 memunit: .int 0 .section .text .globl _start _start: nop movl $result, %ebx movl $116, %eax int $0x80 movl $0, %ebx movl $1, %eax int $0x80 |
$ as -gstabs -o sysinfo.o sysinfo.s $ ld -o sysinfo sysinfo.o $ gdb -q sysinfo Reading symbols from /home/zengl/Downloads/asm_example/syscall/sysinfo...done. (gdb) b *_start Breakpoint 1 at 0x8048074: file sysinfo.s, line 35. (gdb) r Starting program: /home/zengl/Downloads/asm_example/syscall/sysinfo Breakpoint 1, _start () at sysinfo.s:35 35 nop (gdb) s 36 movl $result, %ebx (gdb) s 37 movl $116, %eax (gdb) s 38 int $0x80 (gdb) s 39 movl $0, %ebx (gdb) x/d &uptime 0x8049090 <uptime>: 2453 (gdb) x/d &load1 0x8049094 <load1>: 6432 (gdb) x/d &load5 0x8049098 <load5>: 4544 (gdb) x/d &load15 0x804909c <load15>: 3904 (gdb) x/d &totalram 0x80490a0 <totalram>: 519663616 (gdb) x/d &freeram 0x80490a4 <freeram>: 8466432 (gdb) x/d &sharedram 0x80490a8 <sharedram>: 0 (gdb) x/d &bufferram 0x80490ac <bufferram>: 40206336 (gdb) x/d &totalswap 0x80490b0 <totalswap>: 534769664 (gdb) x/d &freeswap 0x80490b4 <freeswap>: 531910656 (gdb) x/d &procs 0x80490b8 <procs>: 304 (gdb) x/d &totalhigh 0x80490ba <totalhigh>: 0 (gdb) x/d &freehigh 0x80490be <freehigh>: 0 (gdb) x/d &memunit 0x80490c2 <memunit>: 65536 (gdb) |
$ strace ./syscalltest2 execve("./syscalltest2", ["./syscalltest2"], [/* 52 vars */]) = 0 getpid() = 3134 getuid() = 1000 getgid() = 1000 _exit(0) = ? $ |
$ strace -c ./syscalltest2 % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- -nan 0.000000 0 1 execve -nan 0.000000 0 1 getpid -nan 0.000000 0 1 getuid -nan 0.000000 0 1 getgid ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000000 4 total $ |
|
| -e trace=call_list |
|
$ strace -e trace=getpid,getgid ./syscalltest2 getpid() = 2680 getgid() = 1000 $ |
$ strace -o mytrace id uid=1000(zengl) gid=1000(zengl) 组=1000(zengl),4(adm),24(cdrom),27(sudo),29(audio),30(dip),46(plugdev),109(lpadmin),123(sambashare) $ cat mytrace execve("/usr/bin/id", ["id"], [/* 52 vars */]) = 0 brk(0) = 0x9dce000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb76e9000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=87327, ...}) = 0 mmap2(NULL, 87327, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb76d3000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i386-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@A\0\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0644, st_size=120748, ...}) = 0 mmap2(NULL, 125852, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb76b4000 mmap2(0xb76d1000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1c) = 0xb76d1000 close(3) = 0 .......................................... .......................................... $ |
$ strace -c id uid=1000(zengl) gid=1000(zengl) 组=1000(zengl),4(adm),24(cdrom),27(sudo),29(audio),30(dip),46(plugdev),109(lpadmin),123(sambashare) % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 38.71 0.000036 2 17 read 37.63 0.000035 9 4 4 connect 23.66 0.000022 1 32 2 open 0.00 0.000000 0 1 write 0.00 0.000000 0 36 close 0.00 0.000000 0 1 execve 0.00 0.000000 0 9 9 access 0.00 0.000000 0 3 brk 0.00 0.000000 0 19 munmap 0.00 0.000000 0 9 mprotect 0.00 0.000000 0 22 _llseek 0.00 0.000000 0 42 mmap2 0.00 0.000000 0 29 fstat64 0.00 0.000000 0 1 getuid32 0.00 0.000000 0 1 getgid32 0.00 0.000000 0 1 geteuid32 0.00 0.000000 0 1 getegid32 0.00 0.000000 0 2 getgroups32 0.00 0.000000 0 1 set_thread_area 0.00 0.000000 0 1 statfs64 0.00 0.000000 0 4 socket ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000093 236 15 total $ |
$ strace -e trace=open,connect id open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libselinux.so.1", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libdl.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/proc/filesystems", O_RDONLY|O_LARGEFILE) = 3 open("/proc/filesystems", O_RDONLY|O_LARGEFILE) = 3 open("/usr/lib/locale/locale-archive", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3 open("/usr/share/locale/locale.alias", O_RDONLY|O_CLOEXEC) = 3 open("/usr/share/locale/zh_CN/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale/zh/LC_MESSAGES/coreutils.mo", O_RDONLY) = -1 ENOENT (No such file or directory) open("/usr/share/locale-langpack/zh_CN/LC_MESSAGES/coreutils.mo", O_RDONLY) = 3 open("/usr/lib/i386-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 3 connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libnss_compat.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libnsl.so.1", O_RDONLY|O_CLOEXEC) = 3 open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libnss_nis.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/lib/i386-linux-gnu/libnss_files.so.2", O_RDONLY|O_CLOEXEC) = 3 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3 connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory) open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/proc/sys/kernel/ngroups_max", O_RDONLY) = 3 open("/proc/sys/kernel/ngroups_max", O_RDONLY) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 open("/etc/group", O_RDONLY|O_CLOEXEC) = 3 uid=1000(zengl) gid=1000(zengl) 组=1000(zengl),4(adm),24(cdrom),27(sudo),29(audio),30(dip),46(plugdev),109(lpadmin),123(sambashare) $ |
|
# nanotest.s - Another example of using system calls .section .data timespec: .int 5, 0 output: .ascii "This is a test\n" output_end: .equ len, output_end - output .section .bss .lcomm rem, 8 .section .text .globl _start _start: nop movl $10, %ecx loop1: pushl %ecx movl $4, %eax movl $1, %ebx movl $output, %ecx movl $len, %edx int $0x80 movl $162, %eax movl $timespec, %ebx movl $rem, %ecx int $0x80 popl %ecx loop loop1 movl $1, %eax movl $0, %ebx int $0x80 |
NAME
nanosleep - high-resolution sleep
SYNOPSIS
#include
|
|
struct timespec { time_t tv_sec; /* seconds */ long tv_nsec; /* nanoseconds */ }; |
#include <errno.h>
#include <time.h>
int better_sleep (double sleep_time)
{
struct timespec tv;
/* Construct the timespec from the number of whole seconds... */
tv.tv_sec = (time_t) sleep_time;
/* ... and the remainder in nanoseconds. */
tv.tv_nsec = (long) ((sleep_time - tv.tv_sec) * 1e+9);
while (1)
{
/* Sleep for the time specified in tv. If interrupted by a
signal, place the remaining time left to sleep back into tv. */
int rval = nanosleep (&tv, &tv);
if (rval == 0)
/* Completed the entire sleep time; all done. */
return 0;
else if (errno == EINTR)
/* Interrupted by a signal. Try again. */
continue;
else
/* Some other error; bail out. */
return rval;
}
return 0;
}
|
|
timespec: .int 5, 0 .................... .................... .section .bss .lcomm rem, 8 |
|
$ as -gstabs -o nanotest.o nanotest.s $ ld -o nanotest nanotest.o $ ./nanotest This is a test This is a test |
$ su - 密码: root# ps aux | grep nanotest zengl 2885 1.4 5.9 223420 30276 ? Sl 14:48 0:04 gedit /home/zengl/Downloads/asm_example/syscall/nanotest.s zengl 3080 0.0 0.0 148 4 pts/0 S+ 14:53 0:00 ./nanotest root 3082 0.0 0.1 6084 832 pts/1 S+ 14:53 0:00 grep --color=auto nanotest root# strace -p 3080 Process 3080 attached - interrupt to quit restart_syscall(<... resuming interrupted call ...>) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15) = 15 nanosleep({5, 0}, 0x80490d0) = 0 _exit(0) = ? Process 3080 detached root# |
root# ./nanotest & [1] 3217 This is a test root# strace -p 321This is a test 7 Process 3217 attached - interrupt to quit restart_syscall(<... resuming interrupted call ...>) = 0 write(1, "This is a test\n", 15This is a test ) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15This is a test ) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15This is a test ) = 15 nanosleep({5, 0}, 0x80490d0) = 0 write(1, "This is a test\n", 15This is a test ................................... ................................... |
EXIT(3) Linux Programmer's Manual EXIT(3)
NAME
exit - cause normal process termination
SYNOPSIS
#include <stdlib.h>
void exit(int status);
DESCRIPTION
The exit() function causes normal process termination and the value of
status & 0377 is returned to the parent (see wait(2)).
All functions registered with atexit(3) and on_exit(3) are called, in
the reverse order of their registration. (It is possible for one of
these functions to use atexit(3) or on_exit(3) to register an addi‐
tional function to be executed during exit processing; the new regis‐
tration is added to the front of the list of functions that remain to
be called.) If one of these functions does not return (e.g., it calls
_exit(2), or kills itself with a signal), then none of the remaining
functions is called, and further exit processing (in particular, flush‐
ing of stdio(3) streams) is abandoned. If a function has been regis‐
tered multiple times using atexit(3) or on_exit(3), then it is called
as many times as it was registered.
All open stdio(3) streams are flushed and closed. Files created by
tmpfile(3) are removed.
The C standard specifies two constants, EXIT_SUCCESS and EXIT_FAILURE,
that may be passed to exit() to indicate successful or unsuccessful
termination, respectively.
RETURN VALUE
The exit() function does not return.
.....................................................
.....................................................
|
| printf(“The answer is %d\n”, k); |
|
pushl k pushl $output call printf addl $8, %esp |
|
# cfunctest.s - An example of using C functions .section .data output: .asciz "This is a test\n" .section .text .globl _start _start: movl $10, %ecx loop1: pushl %ecx pushl $output call printf addl $4, %esp pushl $5 call sleep addl $4, %esp popl %ecx loop loop1 pushl $0 call exit |
|
$ as -gstabs -o cfunctest.o cfunctest.s $ ld -dynamic-linker /lib/ld-linux.so.2 -lc -o cfunctest cfunctest.o $ |
$ strace ./cfunctest execve("./cfunctest", ["./cfunctest"], [/* 52 vars */]) = 0 brk(0) = 0x95fe000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d8000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=87327, ...}) = 0 mmap2(NULL, 87327, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77c2000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0000\226\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1734120, ...}) = 0 mmap2(NULL, 1743580, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7618000 mmap2(0xb77bc000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a4) = 0xb77bc000 mmap2(0xb77bf000, 10972, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb77bf000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7617000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb7617900, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0xb77bc000, 8192, PROT_READ) = 0 mprotect(0xb77fb000, 4096, PROT_READ) = 0 munmap(0xb77c2000, 87327) = 0 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77d7000 write(1, "This is a test\n", 15This is a test ) = 15 rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0 rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0 rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 nanosleep({5, 0}, 0xbfd65780) = 0 ........................................... ........................................... |
$ strace -rc ./cfunctest This is a test .......................................... .......................................... This is a test % time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 63.16 0.000036 4 10 write 36.84 0.000021 11 2 mprotect 0.00 0.000000 0 1 read 0.00 0.000000 0 2 open 0.00 0.000000 0 2 close 0.00 0.000000 0 1 execve 0.00 0.000000 0 3 3 access 0.00 0.000000 0 1 brk 0.00 0.000000 0 1 munmap 0.00 0.000000 0 10 nanosleep 0.00 0.000000 0 10 rt_sigaction 0.00 0.000000 0 20 rt_sigprocmask 0.00 0.000000 0 7 mmap2 0.00 0.000000 0 3 fstat64 0.00 0.000000 0 1 set_thread_area ------ ----------- ----------- --------- --------- ---------------- 100.00 0.000057 74 3 total $ |