parent
b32c12b311
commit
1c935cf154
@ -1,16 +0,0 @@ |
|||||||
bits 64 |
|
||||||
org 0x400000 |
|
||||||
|
|
||||||
section .text |
|
||||||
mov rax, 1 |
|
||||||
mov rdi, 1 |
|
||||||
lea rsi, [rel msg] |
|
||||||
mov rdx, 14 |
|
||||||
syscall |
|
||||||
|
|
||||||
mov rax, 60 |
|
||||||
xor rdi, rdi |
|
||||||
syscall |
|
||||||
|
|
||||||
section .data |
|
||||||
msg: db "Hello, ring 3!", 10 |
|
||||||
@ -1,8 +1,7 @@ |
|||||||
#include "src/app/cat.h" |
#include "src/kernel/app/cat.h" |
||||||
#include "src/fs.h" |
#include "src/kernel/fs.h" |
||||||
#include "src/memory.h" |
#include "src/kernel/path.h" |
||||||
#include "src/path.h" |
#include "src/lib/memory.h" |
||||||
#include <stdint.h> |
|
||||||
|
|
||||||
void cat(process_t *proc, uint8_t argc, char **argv) { |
void cat(process_t *proc, uint8_t argc, char **argv) { |
||||||
if (argc != 2) { |
if (argc != 2) { |
||||||
@ -1,5 +1,5 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
#include "src/process.h" |
#include "src/kernel/process.h" |
||||||
|
|
||||||
void cat(process_t *proc, uint8_t argc, char **argv); |
void cat(process_t *proc, uint8_t argc, char **argv); |
||||||
@ -1,6 +1,6 @@ |
|||||||
#include "src/app/ls.h" |
#include "src/kernel/app/ls.h" |
||||||
#include "src/fs.h" |
#include "src/kernel/fs.h" |
||||||
#include "src/path.h" |
#include "src/kernel/path.h" |
||||||
#include <stdint.h> |
#include <stdint.h> |
||||||
|
|
||||||
void ls(process_t *proc, uint8_t argc, char **argv) { |
void ls(process_t *proc, uint8_t argc, char **argv) { |
||||||
@ -1,5 +1,5 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
#include "src/process.h" |
#include "src/kernel/process.h" |
||||||
|
|
||||||
void ls(process_t *proc, uint8_t argc, char **argv); |
void ls(process_t *proc, uint8_t argc, char **argv); |
||||||
@ -1,14 +1,12 @@ |
|||||||
#include "src/app/terminal.h" |
#include "src/kernel/app/terminal.h" |
||||||
#include "src/app/cat.h" |
#include "src/kernel/app/cat.h" |
||||||
#include "src/app/ls.h" |
#include "src/kernel/app/ls.h" |
||||||
#include "src/fs.h" |
#include "src/kernel/fs.h" |
||||||
#include "src/memory.h" |
#include "src/kernel/path.h" |
||||||
#include "src/path.h" |
#include "src/kernel/process.h" |
||||||
#include "src/process.h" |
#include "src/lib/memory.h" |
||||||
#include "src/string.h" |
#include "src/lib/string.h" |
||||||
#include "src/util.h" |
#include "src/lib/util.h" |
||||||
|
|
||||||
#include <stdint.h> |
|
||||||
|
|
||||||
static void help(process_t *proc, uint8_t argc, char **argv); |
static void help(process_t *proc, uint8_t argc, char **argv); |
||||||
static void cd(process_t *proc, uint8_t argc, char **argv); |
static void cd(process_t *proc, uint8_t argc, char **argv); |
||||||
@ -1,5 +1,5 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
#include "src/process.h" |
#include "src/kernel/process.h" |
||||||
|
|
||||||
void terminal(process_t *proc, uint8_t argc, char **argv); |
void terminal(process_t *proc, uint8_t argc, char **argv); |
||||||
@ -1,6 +1,6 @@ |
|||||||
#include "src/ata.h" |
#include "src/kernel/ata.h" |
||||||
#include "src/panic.h" |
#include "src/kernel/panic.h" |
||||||
#include "src/util.h" |
#include "src/kernel/util.h" |
||||||
|
|
||||||
#define BSY 0b10000000 |
#define BSY 0b10000000 |
||||||
#define DF 0b00100000 |
#define DF 0b00100000 |
||||||
@ -1,10 +1,10 @@ |
|||||||
#include "src/fat16.h" |
#include "src/kernel/fat16.h" |
||||||
#include "src/ata.h" |
#include "src/kernel/ata.h" |
||||||
#include "src/fs.h" |
#include "src/kernel/fs.h" |
||||||
#include "src/memory.h" |
#include "src/kernel/panic.h" |
||||||
#include "src/string.h" |
#include "src/lib/memory.h" |
||||||
#include "src/util.h" |
#include "src/lib/string.h" |
||||||
#include <stdint.h> |
#include "src/lib/util.h" |
||||||
|
|
||||||
#define SECTOR_SIZE 512 |
#define SECTOR_SIZE 512 |
||||||
#define FIRST_PARTITION_SECTOR 2048 |
#define FIRST_PARTITION_SECTOR 2048 |
||||||
@ -1,6 +1,6 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
#include "src/fs.h" |
#include "src/kernel/fs.h" |
||||||
|
|
||||||
#define FAT16 1 |
#define FAT16 1 |
||||||
|
|
||||||
@ -1,5 +1,5 @@ |
|||||||
#include "src/fs.h" |
#include "src/kernel/fs.h" |
||||||
#include "src/fat16.h" |
#include "src/kernel/fat16.h" |
||||||
|
|
||||||
fs_node_t *fs_mount() { |
fs_node_t *fs_mount() { |
||||||
return fat16_mount(); |
return fat16_mount(); |
||||||
@ -1,6 +1,5 @@ |
|||||||
#include "src/gdt.h" |
#include "src/kernel/gdt.h" |
||||||
#include "src/tss.h" |
#include "src/kernel/tss.h" |
||||||
#include <stdint.h> |
|
||||||
|
|
||||||
typedef struct { |
typedef struct { |
||||||
uint16_t limit_low; |
uint16_t limit_low; |
||||||
@ -1,4 +1,4 @@ |
|||||||
#include "src/idt.h" |
#include "src/kernel/idt.h" |
||||||
|
|
||||||
struct idt_entry { |
struct idt_entry { |
||||||
uint16_t offset_low; |
uint16_t offset_low; |
||||||
@ -1,6 +1,6 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
#include "src/stream.h" |
#include "src/kernel/stream.h" |
||||||
#include <stdint.h> |
#include <stdint.h> |
||||||
|
|
||||||
stream_t *keyboard_init(); |
stream_t *keyboard_init(); |
||||||
@ -0,0 +1,22 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#define PAGE_PRESENT 0x01 |
||||||
|
#define PAGE_WRITABLE 0x02 |
||||||
|
#define PAGE_USER 0x04 |
||||||
|
#define PAGE_PWT 0x08 |
||||||
|
#define PAGE_PCD 0x10 |
||||||
|
#define PAGE_ACCESSED 0x20 |
||||||
|
#define PAGE_DIRTY 0x40 |
||||||
|
#define PAGE_HUGE 0x80 |
||||||
|
#define PAGE_GLOBAL 0x100 |
||||||
|
#define PAGE_NX (1ULL << 63) |
||||||
|
|
||||||
|
void *memory_page_allocate(); |
||||||
|
|
||||||
|
void memory_page_free(void *page); |
||||||
|
|
||||||
|
void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags); |
||||||
|
|
||||||
|
void memory_page_unmap(uint64_t *pml4, void *virt); |
||||||
@ -1,5 +1,5 @@ |
|||||||
#include "src/panic.h" |
#include "src/kernel/panic.h" |
||||||
#include "src/vga.h" |
#include "src/kernel/vga.h" |
||||||
|
|
||||||
void kernel_panic(const char *msg, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { |
void kernel_panic(const char *msg, __attribute__((unused)) const char *file, __attribute__((unused)) int line) { |
||||||
vga_set_string(0, VGA_HEIGHT - 1, msg, 0x28); |
vga_set_string(0, VGA_HEIGHT - 1, msg, 0x28); |
||||||
@ -1,8 +1,8 @@ |
|||||||
#include "src/path.h" |
#include "src/kernel/path.h" |
||||||
#include "src/fs.h" |
#include "src/kernel/fs.h" |
||||||
#include "src/memory.h" |
#include "src/lib/memory.h" |
||||||
#include "src/string.h" |
#include "src/lib/string.h" |
||||||
#include "src/util.h" |
#include "src/lib/util.h" |
||||||
|
|
||||||
path_t *path_open(const fs_node_t *root, const path_t *source, char *path) { |
path_t *path_open(const fs_node_t *root, const path_t *source, char *path) { |
||||||
path_t *result = memory_allocate(sizeof(path_t)); |
path_t *result = memory_allocate(sizeof(path_t)); |
||||||
@ -1,6 +1,6 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
#include "src/fs.h" |
#include "src/kernel/fs.h" |
||||||
#include <stdint.h> |
#include <stdint.h> |
||||||
|
|
||||||
#define PATH_DEPTH 255 |
#define PATH_DEPTH 255 |
||||||
@ -1,5 +1,5 @@ |
|||||||
#include "src/pic.h" |
#include "src/kernel/pic.h" |
||||||
#include "src/util.h" |
#include "src/kernel/util.h" |
||||||
|
|
||||||
static void pic_remap() { |
static void pic_remap() { |
||||||
uint8_t mask1 = inb(0x21); |
uint8_t mask1 = inb(0x21); |
||||||
@ -1,9 +1,9 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
#include "src/fs.h" |
#include "src/kernel/fs.h" |
||||||
#include "src/path.h" |
#include "src/kernel/path.h" |
||||||
#include "src/stream.h" |
#include "src/kernel/stream.h" |
||||||
#include "src/string.h" |
#include "src/lib/string.h" |
||||||
|
|
||||||
#define USER_RFLAGS 0x202 |
#define USER_RFLAGS 0x202 |
||||||
|
|
||||||
@ -1,4 +1,4 @@ |
|||||||
#include "src/tss.h" |
#include "src/kernel/tss.h" |
||||||
|
|
||||||
tss_t tss = { |
tss_t tss = { |
||||||
.iopb_offset = sizeof(tss_t) // points past end of TSS = no I/O permissions
|
.iopb_offset = sizeof(tss_t) // points past end of TSS = no I/O permissions
|
||||||
@ -1,6 +1,7 @@ |
|||||||
#include "src/vga.h" |
#include "src/kernel/vga.h" |
||||||
#include "src/memory.h" |
#include "src/kernel/panic.h" |
||||||
#include "src/util.h" |
#include "src/kernel/util.h" |
||||||
|
#include "src/lib/memory.h" |
||||||
|
|
||||||
static uint16_t *vga = (uint16_t *)0xFFFFFFFF800B8000; |
static uint16_t *vga = (uint16_t *)0xFFFFFFFF800B8000; |
||||||
static uint16_t color = (uint16_t)0x0F << 8; |
static uint16_t color = (uint16_t)0x0F << 8; |
||||||
@ -1,6 +1,6 @@ |
|||||||
#pragma once |
#pragma once |
||||||
|
|
||||||
#include "src/stream.h" |
#include "src/kernel/stream.h" |
||||||
|
|
||||||
#define VGA_WIDTH 80 |
#define VGA_WIDTH 80 |
||||||
#define VGA_HEIGHT 25 |
#define VGA_HEIGHT 25 |
||||||
@ -0,0 +1,26 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#define MEMORY_SIZE 0x08000000 |
||||||
|
#define PAGE_SIZE 4096 |
||||||
|
#define PAGE_COUNT (MEMORY_SIZE / PAGE_SIZE) |
||||||
|
|
||||||
|
#define HEAP_PAGE_COUNT 256 |
||||||
|
#define HEAP_SIZE (HEAP_PAGE_COUNT * PAGE_SIZE) |
||||||
|
|
||||||
|
#define KERNEL_VIRTUAL_BASE 0xFFFFFFFF80000000ULL |
||||||
|
#define PHYS_TO_VIRT(phys) ((void *)((uint64_t)(phys) + KERNEL_VIRTUAL_BASE)) |
||||||
|
#define VIRT_TO_PHYS(virt) ((uint64_t)(virt) - KERNEL_VIRTUAL_BASE) |
||||||
|
|
||||||
|
#define KERNEL_VIRTUAL_PML4 (KERNEL_VIRTUAL_BASE + 0x10000) |
||||||
|
#define KERNEL_VIRTUAL_CODE (KERNEL_VIRTUAL_PML4 + 0x10000) |
||||||
|
#define KERNEL_VIRTUAL_HEAP (KERNEL_VIRTUAL_CODE + 0x100000) |
||||||
|
#define KERNEL_VIRTUAL_UNUSED (KERNEL_VIRTUAL_HEAP + HEAP_SIZE) |
||||||
|
#define KERNEL_VIRTUAL_STACK (KERNEL_VIRTUAL_BASE + 0xF00000 - PAGE_SIZE) |
||||||
|
#define KERNEL_VIRTUAL_STACK_TOP (KERNEL_VIRTUAL_STACK + PAGE_SIZE) |
||||||
|
|
||||||
|
#define USER_VIRTUAL_BASE 0x0000000000000000ULL |
||||||
|
#define USER_VIRTUAL_CODE (USER_VIRTUAL_BASE + 0x400000) |
||||||
|
#define USER_VIRTUAL_HEAP (USER_VIRTUAL_CODE + 0x100000) |
||||||
|
#define USER_VIRTUAL_UNUSED (USER_VIRTUAL_HEAP + HEAP_SIZE) |
||||||
|
#define USER_VIRTUAL_STACK (0x0000700000000000ULL - PAGE_SIZE) |
||||||
|
#define USER_VIRTUAL_STACK_TOP (USER_VIRTUAL_STACK + PAGE_SIZE) |
||||||
@ -0,0 +1,60 @@ |
|||||||
|
#include "src/lib/memory.h" |
||||||
|
#include "src/lib/layout.h" |
||||||
|
#include "src/lib/util.h" |
||||||
|
|
||||||
|
#ifdef KERNEL |
||||||
|
#define HEAP_VIRTUAL_BASE KERNEL_VIRTUAL_HEAP |
||||||
|
#else |
||||||
|
#define HEAP_VIRTUAL_BASE USER_VIRTUAL_HEAP |
||||||
|
#endif |
||||||
|
|
||||||
|
typedef struct free_chunk { |
||||||
|
uint64_t size; // header + data
|
||||||
|
struct free_chunk *next; |
||||||
|
} free_chunk_t; |
||||||
|
|
||||||
|
static free_chunk_t *free_list; |
||||||
|
|
||||||
|
void *memory_allocate(uint64_t size) { |
||||||
|
if (!free_list) { |
||||||
|
free_list = (free_chunk_t *)HEAP_VIRTUAL_BASE; |
||||||
|
free_list->size = HEAP_SIZE; |
||||||
|
free_list->next = NUL; |
||||||
|
} |
||||||
|
|
||||||
|
size = sizeof(free_chunk_t) + (size + 7) & (uint64_t)~7; |
||||||
|
|
||||||
|
free_chunk_t *prev = NUL; |
||||||
|
free_chunk_t *curr = free_list; |
||||||
|
|
||||||
|
while (curr) { |
||||||
|
if (curr->size >= size + (sizeof(free_chunk_t) + 8)) { |
||||||
|
free_chunk_t *remainder = (free_chunk_t *)((uint8_t *)curr + size); |
||||||
|
remainder->size = curr->size - size; |
||||||
|
remainder->next = curr->next; |
||||||
|
curr->size = size; |
||||||
|
curr->next = remainder; |
||||||
|
} |
||||||
|
if (curr->size >= size) { |
||||||
|
if (prev) { |
||||||
|
prev->next = curr->next; |
||||||
|
} else { |
||||||
|
free_list = curr->next; |
||||||
|
} |
||||||
|
void *result = (void *)((uint8_t *)curr + sizeof(free_chunk_t)); |
||||||
|
memory_set(0, size - sizeof(free_chunk_t), result); |
||||||
|
return result; |
||||||
|
} |
||||||
|
prev = curr; |
||||||
|
curr = curr->next; |
||||||
|
} |
||||||
|
|
||||||
|
return NUL; |
||||||
|
} |
||||||
|
|
||||||
|
void memory_free(void *pointer) { |
||||||
|
free_chunk_t *chunk = (free_chunk_t *)((uint8_t *)pointer - sizeof(free_chunk_t)); |
||||||
|
chunk->next = free_list; |
||||||
|
free_list = chunk; |
||||||
|
// TODO Merge adjacent free chunks.
|
||||||
|
} |
||||||
@ -0,0 +1,28 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
void *memory_allocate(uint64_t size); |
||||||
|
|
||||||
|
void memory_free(void *pointer); |
||||||
|
|
||||||
|
static inline void memory_set(uint8_t value, uint64_t bytes, void *to) { |
||||||
|
__asm__ volatile("rep stosb" : "=D"(to), "=c"(bytes) : "D"(to), "a"(value), "c"(bytes) : "memory"); |
||||||
|
} |
||||||
|
|
||||||
|
static inline void memory_move(void *from, uint64_t bytes, void *to) { |
||||||
|
if (to == from) { |
||||||
|
return; |
||||||
|
} else if (to < from) { |
||||||
|
__asm__ volatile("rep movsb" : "=D"(to), "=S"(from), "=c"(bytes) : "D"(to), "S"(from), "c"(bytes) : "memory"); |
||||||
|
} else { |
||||||
|
// TODO ASSERT(0, "memory_move: forward overlapping move not implemented");
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
static inline void memory_copy(const void *from, uint64_t bytes, void *to) { |
||||||
|
// TODO ASSERT((uint64_t)to + bytes <= (uint64_t)from || (uint64_t)to >= (uint64_t)from + bytes, "memory_copy: overlapping backward
|
||||||
|
// copy");
|
||||||
|
|
||||||
|
__asm__ volatile("rep movsb" : "=D"(to), "=S"(from), "=c"(bytes) : "D"(to), "S"(from), "c"(bytes) : "memory"); |
||||||
|
} |
||||||
@ -1,4 +1,4 @@ |
|||||||
#include "src/string.h" |
#include "src/lib/string.h" |
||||||
#include <stdarg.h> |
#include <stdarg.h> |
||||||
|
|
||||||
uint8_t bytes_equal(const char *l, const char *r, uint64_t count) { |
uint8_t bytes_equal(const char *l, const char *r, uint64_t count) { |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#define NUL 0 // TODO Fix VSCode thinking `NULL` conflicts with some other definition.
|
||||||
@ -1,66 +0,0 @@ |
|||||||
#pragma once |
|
||||||
|
|
||||||
#include "src/panic.h" |
|
||||||
#include <stdint.h> |
|
||||||
|
|
||||||
#define PAGE_PRESENT 0x01 |
|
||||||
#define PAGE_WRITABLE 0x02 |
|
||||||
#define PAGE_USER 0x04 |
|
||||||
#define PAGE_PWT 0x08 |
|
||||||
#define PAGE_PCD 0x10 |
|
||||||
#define PAGE_ACCESSED 0x20 |
|
||||||
#define PAGE_DIRTY 0x40 |
|
||||||
#define PAGE_HUGE 0x80 |
|
||||||
#define PAGE_GLOBAL 0x100 |
|
||||||
#define PAGE_NX (1ULL << 63) |
|
||||||
|
|
||||||
#define MEMORY_SIZE 0x08000000 |
|
||||||
#define PAGE_SIZE 4096 |
|
||||||
#define PAGE_COUNT (MEMORY_SIZE / PAGE_SIZE) |
|
||||||
|
|
||||||
#define HEAP_PAGE_COUNT 256 |
|
||||||
|
|
||||||
#define KERNEL_VIRTUAL_BASE 0xFFFFFFFF80000000ULL |
|
||||||
#define PHYS_TO_VIRT(phys) ((void *)((uint64_t)(phys) + KERNEL_VIRTUAL_BASE)) |
|
||||||
#define VIRT_TO_PHYS(virt) ((uint64_t)(virt) - KERNEL_VIRTUAL_BASE) |
|
||||||
|
|
||||||
#define KERNEL_PML4 0xFFFFFFFF80010000ULL |
|
||||||
|
|
||||||
#define USER_VIRTUAL_BASE 0x0000000000000000ULL |
|
||||||
#define USER_VIRTUAL_CODE (USER_VIRTUAL_BASE + 0x400000) |
|
||||||
#define USER_VIRTUAL_HEAP (USER_VIRTUAL_CODE + 0x400000) |
|
||||||
#define USER_VIRTUAL_STACK (0x0000700000000000ULL - PAGE_SIZE) |
|
||||||
|
|
||||||
void memory_init(); |
|
||||||
|
|
||||||
void *memory_page_allocate(); |
|
||||||
|
|
||||||
void memory_page_free(void *page); |
|
||||||
|
|
||||||
void memory_page_map(uint64_t *pml4, void *virt, void *phys, uint64_t flags); |
|
||||||
|
|
||||||
void memory_page_unmap(uint64_t *pml4, void *virt); |
|
||||||
|
|
||||||
void *memory_allocate(uint64_t size); |
|
||||||
|
|
||||||
void memory_free(void *pointer); |
|
||||||
|
|
||||||
static inline void memory_set(uint8_t value, uint64_t bytes, void *to) { |
|
||||||
__asm__ volatile("rep stosb" : "=D"(to), "=c"(bytes) : "D"(to), "a"(value), "c"(bytes) : "memory"); |
|
||||||
} |
|
||||||
|
|
||||||
static inline void memory_move(void *from, uint64_t bytes, void *to) { |
|
||||||
if (to == from) { |
|
||||||
return; |
|
||||||
} else if (to < from) { |
|
||||||
__asm__ volatile("rep movsb" : "=D"(to), "=S"(from), "=c"(bytes) : "D"(to), "S"(from), "c"(bytes) : "memory"); |
|
||||||
} else { |
|
||||||
ASSERT(0, "memory_move: forward overlapping move not implemented"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
static inline void memory_copy(const void *from, uint64_t bytes, void *to) { |
|
||||||
ASSERT((uint64_t)to + bytes <= (uint64_t)from || (uint64_t)to >= (uint64_t)from + bytes, "memory_copy: overlapping backward copy"); |
|
||||||
|
|
||||||
__asm__ volatile("rep movsb" : "=D"(to), "=S"(from), "=c"(bytes) : "D"(to), "S"(from), "c"(bytes) : "memory"); |
|
||||||
} |
|
||||||
@ -0,0 +1,6 @@ |
|||||||
|
#include "src/user/syscall.h" |
||||||
|
|
||||||
|
int main() { |
||||||
|
write(1, "Hello from C!\n", 14); |
||||||
|
return 0; |
||||||
|
} |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
ENTRY(_start) |
||||||
|
|
||||||
|
SECTIONS { |
||||||
|
. = 0x0000000000400000; |
||||||
|
|
||||||
|
.text : { *(.text) } |
||||||
|
.rodata : { *(.rodata) } |
||||||
|
.data : { *(.data) } |
||||||
|
.bss : { *(.bss) } |
||||||
|
} |
||||||
@ -0,0 +1,10 @@ |
|||||||
|
bits 64 |
||||||
|
|
||||||
|
extern main |
||||||
|
|
||||||
|
global _start |
||||||
|
_start: |
||||||
|
call main |
||||||
|
mov rdi, rax ; return value |
||||||
|
mov rax, 60 ; exit syscall |
||||||
|
syscall |
||||||
@ -0,0 +1,13 @@ |
|||||||
|
bits 64 |
||||||
|
|
||||||
|
global write |
||||||
|
write: |
||||||
|
mov rax, 1 |
||||||
|
syscall |
||||||
|
ret |
||||||
|
|
||||||
|
global exit |
||||||
|
exit: |
||||||
|
mov rax, 60 |
||||||
|
syscall |
||||||
|
; never returns |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
void write(int64_t fd, const void *data, uint64_t bytes); |
||||||
|
|
||||||
|
void exit(); |
||||||
Loading…
Reference in new issue