Skip to content

Instantly share code, notes, and snippets.

@david4958606
Created March 7, 2025 02:36
Show Gist options
  • Save david4958606/611bd62714d470a3991952e29e6a3aba to your computer and use it in GitHub Desktop.
Save david4958606/611bd62714d470a3991952e29e6a3aba to your computer and use it in GitHub Desktop.
# 编译器和汇编器
CC = gcc
NASM = nasm
# 编译、汇编和链接选项
# -nostdlib 和 -nostartfiles 用于防止引入系统启动文件和标准库
CFLAGS = -static -O2 -nostdlib -nostartfiles -Wall -Wextra -m64
LDFLAGS = -static -m64 -nostdlib -nostartfiles
ASMFLAGS = -f elf64
# 目标文件和生成的可执行文件名
TARGET = mysh
OBJS = mysh.o syscalls.o
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS)
mysh.o: mysh.c
$(CC) $(CFLAGS) -c -o $@ mysh.c
syscalls.o: syscalls.asm
$(NASM) $(ASMFLAGS) -o $@ syscalls.asm
clean:
rm -f $(TARGET) $(OBJS)
#define _GNU_SOURCE
#include <sys/types.h>
#define NULL ((void*)0) // 手动定义 NULL
// 声明汇编函数
ssize_t syscall_read(int fd, void* buf, size_t count);
ssize_t syscall_write(int fd, const void* buf, size_t count);
pid_t syscall_fork(void);
int syscall_execve(const char* path, char* const argv[], char* const envp[]);
pid_t syscall_wait4(int pid, int* status, int options, void* rusage);
void syscall_exit(int status);
#define MAX_ARGS 64
#define MAX_LINE 1024
// 自定义简单参数分割
int split_args(char* line, char** args)
{
int i = 0;
while (*line != '\0' && i < MAX_ARGS - 1)
{
while (*line == ' ')
*line++ = '\0';
if (*line)
args[i++] = line;
while (*line && *line != ' ')
line++;
}
args[i] = NULL;
return i;
}
void _start()
{
char cmd[MAX_LINE];
char* args[MAX_ARGS];
const char prompt[] = "mysh> ";
while (1)
{
syscall_write(1, prompt, sizeof(prompt) - 1);
ssize_t len = syscall_read(0, cmd, MAX_LINE);
if (len <= 0)
syscall_exit(1);
cmd[len - 1] = '\0'; // 去掉换行符
if (!split_args(cmd, args))
continue;
if (args[0][0] == 'e' && args[0][1] == 'x' && args[0][2] == 'i'
&& args[0][3] == 't' && args[0][4] == '\0')
{
syscall_exit(0);
}
pid_t pid = syscall_fork();
if (pid == 0)
{ // 子进程
syscall_execve(args[0], args, NULL);
const char err[] = "execve failed\n";
syscall_write(2, err, sizeof(err) - 1);
syscall_exit(1);
}
else if (pid > 0)
{ // 父进程
syscall_wait4(pid, NULL, 0, NULL);
}
}
}
; syscalls.asm
section .text
global syscall_read, syscall_write, syscall_execve
global syscall_fork, syscall_wait4, syscall_exit
; ssize_t syscall_read(int fd, void *buf, size_t count)
syscall_read:
mov rax, 0 ; sys_read
syscall
ret
; ssize_t syscall_write(int fd, const void *buf, size_t count)
syscall_write:
mov rax, 1 ; sys_write
syscall
ret
; pid_t syscall_fork(void)
syscall_fork:
mov rax, 57 ; sys_fork
syscall
ret
; int syscall_execve(const char *filename, char *const argv[], char *const envp[])
syscall_execve:
mov rax, 59 ; sys_execve
syscall
ret
; pid_t syscall_wait4(int pid, int *status, int options, struct rusage *rusage)
syscall_wait4:
mov rax, 61 ; sys_wait4
syscall
ret
; void syscall_exit(int status)
syscall_exit:
mov rax, 60 ; sys_exit
syscall
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment