106 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* syscall.c
 | 
						|
 *
 | 
						|
 * Call OS functions without using libc. The example `my_print` could be done in
 | 
						|
 * different flavors:
 | 
						|
 *
 | 
						|
 * **my_print_64:**
 | 
						|
 *   Using the SYSCALL instruction (successor to SYSENTER). Should work for both
 | 
						|
 *   IA-64 and AMD64 CPUs, can be ported to `my_print_trap` (see there).
 | 
						|
 *   Register usage:
 | 
						|
 *
 | 
						|
 *     - RAX: pass syscall number, hold return value from syscall execution
 | 
						|
 *     - RDI: syscall argument 1
 | 
						|
 *     - RSI: syscall argument 2
 | 
						|
 *     - RDX: syscall argument 3
 | 
						|
 *
 | 
						|
 * **my_print_trap:**
 | 
						|
 *   Using the trap interrupt to switch to kernel mode. Slower, but
 | 
						|
 *   architecturally neutral. Register usage:
 | 
						|
 *
 | 
						|
 *     - EAX: pass syscall number, hold return value from syscall execution
 | 
						|
 *     - EBX: syscall argument 1
 | 
						|
 *     - ECX: syscall argument 2
 | 
						|
 *     - EDX: syscall argument 3
 | 
						|
 */
 | 
						|
 | 
						|
#include <asm/unistd.h> /* compile with -m32 for 32-bit syscall numbers,
 | 
						|
                           without for 64-bit syscall numbers. */
 | 
						|
/* simple inline assembler (asm) requires global symbols */
 | 
						|
#define __NR_exit 60
 | 
						|
// text buffer pointer
 | 
						|
char *my_print_text;
 | 
						|
// text buffer length, print return value
 | 
						|
int my_print_len, my_print_ret;
 | 
						|
// write() syscall number
 | 
						|
int call_write;
 | 
						|
int exitnum; 
 | 
						|
 | 
						|
int my_print_64(char *text) {
 | 
						|
    my_print_text = text;
 | 
						|
 | 
						|
    /* strlen(my_print_text) manually */
 | 
						|
    for (my_print_len = 0; my_print_text[my_print_len]; ++my_print_len);
 | 
						|
 | 
						|
    /* system call signature:
 | 
						|
     * ssize_t write(int fd, const void *buf, size_t count);
 | 
						|
     *
 | 
						|
     * write() system call number is defined by __NR_write
 | 
						|
     */
 | 
						|
    call_write = __NR_write;
 | 
						|
    /* stdout is file descriptor no. 1 */
 | 
						|
    asm("mov call_write, %rax");    /* arg 0 (rax): syscall number  */
 | 
						|
    asm("mov $1, %rdi");            /* arg 1 (rdi): file descriptor */
 | 
						|
    asm("mov my_print_text, %rsi"); /* arg 2 (rsi): buffer          */
 | 
						|
    asm("mov my_print_len, %rdx");  /* arg 3 (rdx): length          */
 | 
						|
    asm("syscall");                 /* SYSCALL instruction          */
 | 
						|
    asm("mov %rax, my_print_ret");  /* save return code (rax)       */
 | 
						|
 | 
						|
    return my_print_ret;
 | 
						|
}
 | 
						|
 | 
						|
int my_print_trap(char *text) {
 | 
						|
    /* system call signature: see my_print_64 */
 | 
						|
 | 
						|
    /* TODO */
 | 
						|
 | 
						|
    return 7;
 | 
						|
}
 | 
						|
 | 
						|
/* simple inline assembler (asm) requires global symbols */
 | 
						|
 | 
						|
// exit return value
 | 
						|
int my_exit_status;
 | 
						|
 | 
						|
void my_exit_64(int status) {
 | 
						|
    my_exit_status = status;
 | 
						|
 | 
						|
    /* system call signature:
 | 
						|
     * void exit(int status);
 | 
						|
     *
 | 
						|
     * exit() system call number is defined by __NR_exit
 | 
						|
     */
 | 
						|
 | 
						|
    /* TODO */
 | 
						|
    // Syscall
 | 
						|
   //exitnum = __NR_exit;
 | 
						|
   //asm("mov $60, %rax"); // verwende den exitnum / 60 Syscall
 | 
						|
   //asm("mov my_exit_status, %rdi"); //status = myexitstatus oder 0 
 | 
						|
   //asm("syscall");
 | 
						|
   //TRAP 
 | 
						|
   asm("mov $1, %eax");
 | 
						|
   asm("mov my_exit_status, %ebx");
 | 
						|
   asm("int $0x80"); 
 | 
						|
   
 | 
						|
 | 
						|
  
 | 
						|
}
 | 
						|
 | 
						|
int main(void) {
 | 
						|
    my_print_64("Hello World!\n");
 | 
						|
 | 
						|
    my_exit_64(42);
 | 
						|
 | 
						|
    /* never come here, if my_exit_64 works */
 | 
						|
    return 6;
 | 
						|
}
 |