Informatik/Assets/Betriebssysteme_uebung/u6-a1-anlage/syscall.c
2021-03-01 16:39:46 +01:00

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;
}