Zhou Zixuan Original works reproduced please specify the source "Linux kernel Analysis" MOOC course http://mooc.study.163.com/course/USTC-1000029000
Use the same system call using the Library function API and the embed assembly code in C code two waysmethod One: Use the API to display "Hello World" on the screen
This is actually a C language classic introductory program, the source code is as follows
- #include "stdio.h"
- #include "string.h"
- int main ()
- {
- char* msg = "Hello World";
- printf ("%s", msg);
- return 0;
- }
In the lab building, open the Experiment Link (http://www.shiyanlou.com/courses/running/731), double-click Xfce Terminal, CD code directory, gedit HELLOWORLD.C, create and open the Helloworld.c file, enter the above code, save the exit;
Then use the following instructions to compile the linker:
Gcc-o HelloWorld Helloworld.c-m32
Next, run the compiled program,
./helloworld
The effect is as follows:
method Two: Use C inline assembler code to output HelloWorld on the screen
The syntax of the inline assembler code in Linux, which is described in detail in the video, is omitted here, directly giving the code and comments as follows:
- int main ()
- {
- char* msg = "Hello World";
- int len = 11;
- int result = 0;
- __asm__ __volatile__ ("Movl%2,%%edx;\n\r"/* passed in Parameter: length of string to display */
- "Movl%1,%%ecx;\n\r"/* Incoming entry: File descriptor (STDOUT) */
- "Movl $,%%ebx;\n\r"/* passed in Parameter: the string to display */
- "Movl $4,%%eax;\n\r"/* System call Number: 4 sys_write*/
- "Int $0x80"/* Triggers system call interruption */
- : "=m" (Result)//output section: This example does not use the */
- : "M" (msg), "R" (len)/* Input part: Binding string and string length variable */
- : "%eax");
- return 0;
- }
Use Gedit helloworld_asm.c to create a new file and enter the code above, using the following command to compile
Gcc-o helloworld_asm Helloworld_asm.c-m32
Run with the following command
./helloworld_asm
Run the following effect
Summary
Even the simplest programs will inevitably use operations such as input, output, and exit, while doing so requires invoking the service provided by the operating system, which is called the system. Unless your program only completes mathematical operations such as subtraction, it is difficult to avoid using system calls. There are two ways to make a system call under the Linux platform: by using the encapsulated C Library (LIBC) or by assembly-direct invocation.
System calls under Linux are implemented by means of interrupts (int 0x80). When the int 80 instruction is executed, the function number of the system call is stored in the register eax, and the parameters passed to the system call must be placed in the Register Ebx,ecx,edx,esi,edi in order, and when the system call is complete, the return value can be obtained in the register EAX.
All system call function numbers can be found in the file/usr/include/bits/syscall.h, for ease of use, they are defined with a macro such as sys_<name>, such as Sys_write, Sys_exit, and so on. For example, the write function that is often used is defined as follows:
ssize_t Write (int fd, const void *buf, size_t count);
The function is ultimately implemented by Sys_write, the system call. According to the above conventions, the parameters FB, BUF and count respectively exist in registers ebx, ECX and edx, and the system call number Sys_write is placed in register EAX, when the int 0x80 instruction is executed, the return value can be obtained from register EAX.
Perhaps you have found that at most only 5 registers can be used to save parameters when making system calls, is there not more than 5 parameters for all system calls? Of course not, for example, the MMAP function has 6 parameters, which need to be passed to the system call Sys_mmap at the end:
void * Mmap (void *start, size_t length, int prot, int flags, int fd, off_t offset);
When the number of parameters required for a system call is greater than 5 o'clock, the execution of the int 0x80 instruction is still required to save the system call function number in the register eax, except that all parameters should be placed sequentially in a contiguous area of memory while holding a pointer to the memory area in the register EBX. After the system call is complete, the return value will still be saved in the register EAX.
Because only a contiguous area of memory is required to hold the parameters of the system call, it is entirely possible to use the stack to pass the parameters required by the system call like normal function calls. Note, however, that Linux uses the C-language invocation pattern, which means that all parameters must be stacked in the opposite order, that is, the last parameter is first in the stack, and the first parameter is the last one in the stack. If the stack is used to pass the parameters required by the system call, the current value of the stack pointer should also be copied to the register ebx when the int 0x80 instruction is executed.
Linux Kernel Analysis 4