add lab4 spoc exercises

This commit is contained in:
chyyuu 2016-04-11 00:58:26 +08:00
parent 91d8793b24
commit 28605e36e7
10 changed files with 712 additions and 0 deletions

View File

@ -0,0 +1,3 @@
as -gstabs --32 -o callee.o callee.s
gcc -m32 -g -c -fno-stack-protector caller.c
gcc -m32 -g -o caller caller.o callee.o

View File

@ -0,0 +1,2 @@
as -arch i386 -o prog.o prog.s
ld -arch i386 -o prog prog.o

View File

@ -0,0 +1,5 @@
int addtwo(int a)
{
int x = 2;
return a + x;
}

View File

@ -0,0 +1,11 @@
void func2(int a, int b)
{
a++;
b+=2;
}
int main()
{
func2( 1111, 2222);
return 0;
}

View File

@ -0,0 +1,218 @@
call2: file format elf32-i386
Disassembly of section .init:
08048294 <_init>:
8048294: 53 push %ebx
8048295: 83 ec 08 sub $0x8,%esp
8048298: e8 83 00 00 00 call 8048320 <__x86.get_pc_thunk.bx>
804829d: 81 c3 63 1d 00 00 add $0x1d63,%ebx
80482a3: 8b 83 fc ff ff ff mov -0x4(%ebx),%eax
80482a9: 85 c0 test %eax,%eax
80482ab: 74 05 je 80482b2 <_init+0x1e>
80482ad: e8 1e 00 00 00 call 80482d0 <__gmon_start__@plt>
80482b2: 83 c4 08 add $0x8,%esp
80482b5: 5b pop %ebx
80482b6: c3 ret
Disassembly of section .plt:
080482c0 <__gmon_start__@plt-0x10>:
80482c0: ff 35 04 a0 04 08 pushl 0x804a004
80482c6: ff 25 08 a0 04 08 jmp *0x804a008
80482cc: 00 00 add %al,(%eax)
...
080482d0 <__gmon_start__@plt>:
80482d0: ff 25 0c a0 04 08 jmp *0x804a00c
80482d6: 68 00 00 00 00 push $0x0
80482db: e9 e0 ff ff ff jmp 80482c0 <_init+0x2c>
080482e0 <__libc_start_main@plt>:
80482e0: ff 25 10 a0 04 08 jmp *0x804a010
80482e6: 68 08 00 00 00 push $0x8
80482eb: e9 d0 ff ff ff jmp 80482c0 <_init+0x2c>
Disassembly of section .text:
080482f0 <main>:
int main()
{
func2( 1111, 2222);
return 0;
}
80482f0: 31 c0 xor %eax,%eax
80482f2: c3 ret
080482f3 <_start>:
80482f3: 31 ed xor %ebp,%ebp
80482f5: 5e pop %esi
80482f6: 89 e1 mov %esp,%ecx
80482f8: 83 e4 f0 and $0xfffffff0,%esp
80482fb: 50 push %eax
80482fc: 54 push %esp
80482fd: 52 push %edx
80482fe: 68 60 84 04 08 push $0x8048460
8048303: 68 00 84 04 08 push $0x8048400
8048308: 51 push %ecx
8048309: 56 push %esi
804830a: 68 f0 82 04 08 push $0x80482f0
804830f: e8 cc ff ff ff call 80482e0 <__libc_start_main@plt>
8048314: f4 hlt
8048315: 66 90 xchg %ax,%ax
8048317: 66 90 xchg %ax,%ax
8048319: 66 90 xchg %ax,%ax
804831b: 66 90 xchg %ax,%ax
804831d: 66 90 xchg %ax,%ax
804831f: 90 nop
08048320 <__x86.get_pc_thunk.bx>:
8048320: 8b 1c 24 mov (%esp),%ebx
8048323: c3 ret
8048324: 66 90 xchg %ax,%ax
8048326: 66 90 xchg %ax,%ax
8048328: 66 90 xchg %ax,%ax
804832a: 66 90 xchg %ax,%ax
804832c: 66 90 xchg %ax,%ax
804832e: 66 90 xchg %ax,%ax
08048330 <deregister_tm_clones>:
8048330: b8 1f a0 04 08 mov $0x804a01f,%eax
8048335: 2d 1c a0 04 08 sub $0x804a01c,%eax
804833a: 83 f8 06 cmp $0x6,%eax
804833d: 76 1a jbe 8048359 <deregister_tm_clones+0x29>
804833f: b8 00 00 00 00 mov $0x0,%eax
8048344: 85 c0 test %eax,%eax
8048346: 74 11 je 8048359 <deregister_tm_clones+0x29>
8048348: 55 push %ebp
8048349: 89 e5 mov %esp,%ebp
804834b: 83 ec 14 sub $0x14,%esp
804834e: 68 1c a0 04 08 push $0x804a01c
8048353: ff d0 call *%eax
8048355: 83 c4 10 add $0x10,%esp
8048358: c9 leave
8048359: f3 c3 repz ret
804835b: 90 nop
804835c: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
08048360 <register_tm_clones>:
8048360: b8 1c a0 04 08 mov $0x804a01c,%eax
8048365: 2d 1c a0 04 08 sub $0x804a01c,%eax
804836a: c1 f8 02 sar $0x2,%eax
804836d: 89 c2 mov %eax,%edx
804836f: c1 ea 1f shr $0x1f,%edx
8048372: 01 d0 add %edx,%eax
8048374: d1 f8 sar %eax
8048376: 74 1b je 8048393 <register_tm_clones+0x33>
8048378: ba 00 00 00 00 mov $0x0,%edx
804837d: 85 d2 test %edx,%edx
804837f: 74 12 je 8048393 <register_tm_clones+0x33>
8048381: 55 push %ebp
8048382: 89 e5 mov %esp,%ebp
8048384: 83 ec 10 sub $0x10,%esp
8048387: 50 push %eax
8048388: 68 1c a0 04 08 push $0x804a01c
804838d: ff d2 call *%edx
804838f: 83 c4 10 add $0x10,%esp
8048392: c9 leave
8048393: f3 c3 repz ret
8048395: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
8048399: 8d bc 27 00 00 00 00 lea 0x0(%edi,%eiz,1),%edi
080483a0 <__do_global_dtors_aux>:
80483a0: 80 3d 1c a0 04 08 00 cmpb $0x0,0x804a01c
80483a7: 75 13 jne 80483bc <__do_global_dtors_aux+0x1c>
80483a9: 55 push %ebp
80483aa: 89 e5 mov %esp,%ebp
80483ac: 83 ec 08 sub $0x8,%esp
80483af: e8 7c ff ff ff call 8048330 <deregister_tm_clones>
80483b4: c6 05 1c a0 04 08 01 movb $0x1,0x804a01c
80483bb: c9 leave
80483bc: f3 c3 repz ret
80483be: 66 90 xchg %ax,%ax
080483c0 <frame_dummy>:
80483c0: b8 10 9f 04 08 mov $0x8049f10,%eax
80483c5: 8b 10 mov (%eax),%edx
80483c7: 85 d2 test %edx,%edx
80483c9: 75 05 jne 80483d0 <frame_dummy+0x10>
80483cb: eb 93 jmp 8048360 <register_tm_clones>
80483cd: 8d 76 00 lea 0x0(%esi),%esi
80483d0: ba 00 00 00 00 mov $0x0,%edx
80483d5: 85 d2 test %edx,%edx
80483d7: 74 f2 je 80483cb <frame_dummy+0xb>
80483d9: 55 push %ebp
80483da: 89 e5 mov %esp,%ebp
80483dc: 83 ec 14 sub $0x14,%esp
80483df: 50 push %eax
80483e0: ff d2 call *%edx
80483e2: 83 c4 10 add $0x10,%esp
80483e5: c9 leave
80483e6: e9 75 ff ff ff jmp 8048360 <register_tm_clones>
80483eb: 66 90 xchg %ax,%ax
80483ed: 66 90 xchg %ax,%ax
80483ef: 90 nop
080483f0 <func2>:
void func2(int a, int b)
{
80483f0: f3 c3 repz ret
80483f2: 66 90 xchg %ax,%ax
80483f4: 66 90 xchg %ax,%ax
80483f6: 66 90 xchg %ax,%ax
80483f8: 66 90 xchg %ax,%ax
80483fa: 66 90 xchg %ax,%ax
80483fc: 66 90 xchg %ax,%ax
80483fe: 66 90 xchg %ax,%ax
08048400 <__libc_csu_init>:
8048400: 55 push %ebp
8048401: 57 push %edi
8048402: 31 ff xor %edi,%edi
8048404: 56 push %esi
8048405: 53 push %ebx
8048406: e8 15 ff ff ff call 8048320 <__x86.get_pc_thunk.bx>
804840b: 81 c3 f5 1b 00 00 add $0x1bf5,%ebx
8048411: 83 ec 0c sub $0xc,%esp
8048414: 8b 6c 24 20 mov 0x20(%esp),%ebp
8048418: 8d b3 0c ff ff ff lea -0xf4(%ebx),%esi
804841e: e8 71 fe ff ff call 8048294 <_init>
8048423: 8d 83 08 ff ff ff lea -0xf8(%ebx),%eax
8048429: 29 c6 sub %eax,%esi
804842b: c1 fe 02 sar $0x2,%esi
804842e: 85 f6 test %esi,%esi
8048430: 74 23 je 8048455 <__libc_csu_init+0x55>
8048432: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
8048438: 83 ec 04 sub $0x4,%esp
804843b: ff 74 24 2c pushl 0x2c(%esp)
804843f: ff 74 24 2c pushl 0x2c(%esp)
8048443: 55 push %ebp
8048444: ff 94 bb 08 ff ff ff call *-0xf8(%ebx,%edi,4)
804844b: 83 c7 01 add $0x1,%edi
804844e: 83 c4 10 add $0x10,%esp
8048451: 39 f7 cmp %esi,%edi
8048453: 75 e3 jne 8048438 <__libc_csu_init+0x38>
8048455: 83 c4 0c add $0xc,%esp
8048458: 5b pop %ebx
8048459: 5e pop %esi
804845a: 5f pop %edi
804845b: 5d pop %ebp
804845c: c3 ret
804845d: 8d 76 00 lea 0x0(%esi),%esi
08048460 <__libc_csu_fini>:
8048460: f3 c3 repz ret
Disassembly of section .fini:
08048464 <_fini>:
8048464: 53 push %ebx
8048465: 83 ec 08 sub $0x8,%esp
8048468: e8 b3 fe ff ff call 8048320 <__x86.get_pc_thunk.bx>
804846d: 81 c3 93 1b 00 00 add $0x1b93,%ebx
8048473: 83 c4 08 add $0x8,%esp
8048476: 5b pop %ebx
8048477: c3 ret

View File

@ -0,0 +1,17 @@
.code32
SYSWRITE = 4 # sys_write()
.global mywrite
.text
mywrite:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl 8(%ebp),%ebx # ebx
movl 12(%ebp),%ecx # ecx
movl 16(%ebp),%edx # edx
movl $SYSWRITE,%eax # eax
int $0x80
popl %ebx
mov %ebp, %esp
popl %ebp
ret

View File

@ -0,0 +1,7 @@
#include <string.h>
int main()
{
char* mystr = "Welcome to baby OS!\n";
mywrite(1, mystr, strlen(mystr));
return 0;
}

View File

@ -0,0 +1,411 @@
#include <proc.h>
#include <kmalloc.h>
#include <string.h>
#include <sync.h>
#include <pmm.h>
#include <error.h>
#include <sched.h>
#include <elf.h>
#include <vmm.h>
#include <trap.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* ------------- process/thread mechanism design&implementation -------------
(an simplified Linux process/thread mechanism )
introduction:
ucore implements a simple process/thread mechanism. process contains the independent memory sapce, at least one threads
for execution, the kernel data(for management), processor state (for context switch), files(in lab6), etc. ucore needs to
manage all these details efficiently. In ucore, a thread is just a special kind of process(share process's memory).
------------------------------
process state : meaning -- reason
PROC_UNINIT : uninitialized -- alloc_proc
PROC_SLEEPING : sleeping -- try_free_pages, do_wait, do_sleep
PROC_RUNNABLE : runnable(maybe running) -- proc_init, wakeup_proc,
PROC_ZOMBIE : almost dead -- do_exit
-----------------------------
process state changing:
alloc_proc RUNNING
+ +--<----<--+
+ + proc_run +
V +-->---->--+
PROC_UNINIT -- proc_init/wakeup_proc --> PROC_RUNNABLE -- try_free_pages/do_wait/do_sleep --> PROC_SLEEPING --
A + +
| +--- do_exit --> PROC_ZOMBIE +
+ +
-----------------------wakeup_proc----------------------------------
-----------------------------
process relations
parent: proc->parent (proc is children)
children: proc->cptr (proc is parent)
older sibling: proc->optr (proc is younger sibling)
younger sibling: proc->yptr (proc is older sibling)
-----------------------------
related syscall for process:
SYS_exit : process exit, -->do_exit
SYS_fork : create child process, dup mm -->do_fork-->wakeup_proc
SYS_wait : wait process -->do_wait
SYS_exec : after fork, process execute a program -->load a program and refresh the mm
SYS_clone : create child thread -->do_fork-->wakeup_proc
SYS_yield : process flag itself need resecheduling, -- proc->need_sched=1, then scheduler will rescheule this process
SYS_sleep : process sleep -->do_sleep
SYS_kill : kill process -->do_kill-->proc->flags |= PF_EXITING
-->wakeup_proc-->do_wait-->do_exit
SYS_getpid : get the process's pid
*/
// the process set's list
list_entry_t proc_list;
#define HASH_SHIFT 10
#define HASH_LIST_SIZE (1 << HASH_SHIFT)
#define pid_hashfn(x) (hash32(x, HASH_SHIFT))
// has list for process set based on pid
static list_entry_t hash_list[HASH_LIST_SIZE];
// idle proc
struct proc_struct *idleproc = NULL;
// init proc
struct proc_struct *initproc = NULL;
// current proc
struct proc_struct *current = NULL;
static int nr_process = 0;
void kernel_thread_entry(void);
void forkrets(struct trapframe *tf);
void switch_to(struct context *from, struct context *to);
// alloc_proc - alloc a proc_struct and init all fields of proc_struct
static struct proc_struct *
alloc_proc(void) {
struct proc_struct *proc = kmalloc(sizeof(struct proc_struct));
if (proc != NULL) {
//LAB4:EXERCISE1 YOUR CODE
/*
* below fields in proc_struct need to be initialized
* enum proc_state state; // Process state
* int pid; // Process ID
* int runs; // the running times of Proces
* uintptr_t kstack; // Process kernel stack
* volatile bool need_resched; // bool value: need to be rescheduled to release CPU?
* struct proc_struct *parent; // the parent process
* struct mm_struct *mm; // Process's memory management field
* struct context context; // Switch here to run process
* struct trapframe *tf; // Trap frame for current interrupt
* uintptr_t cr3; // CR3 register: the base addr of Page Directroy Table(PDT)
* uint32_t flags; // Process flag
* char name[PROC_NAME_LEN + 1]; // Process name
*/
proc->state = PROC_UNINIT;
proc->pid = -1;
proc->runs = 0;
proc->kstack = 0;
proc->need_resched = 0;
proc->parent = NULL;
proc->mm = NULL;
memset(&(proc->context), 0, sizeof(struct context));
proc->tf = NULL;
proc->cr3 = boot_cr3;
proc->flags = 0;
memset(proc->name, 0, PROC_NAME_LEN);
}
return proc;
}
// set_proc_name - set the name of proc
char *
set_proc_name(struct proc_struct *proc, const char *name) {
memset(proc->name, 0, sizeof(proc->name));
return memcpy(proc->name, name, PROC_NAME_LEN);
}
// get_proc_name - get the name of proc
char *
get_proc_name(struct proc_struct *proc) {
static char name[PROC_NAME_LEN + 1];
memset(name, 0, sizeof(name));
return memcpy(name, proc->name, PROC_NAME_LEN);
}
// get_pid - alloc a unique pid for process
static int
get_pid(void) {
static_assert(MAX_PID > MAX_PROCESS);
struct proc_struct *proc;
list_entry_t *list = &proc_list, *le;
static int next_safe = MAX_PID, last_pid = MAX_PID;
if (++ last_pid >= MAX_PID) {
last_pid = 1;
goto inside;
}
if (last_pid >= next_safe) {
inside:
next_safe = MAX_PID;
repeat:
le = list;
while ((le = list_next(le)) != list) {
proc = le2proc(le, list_link);
if (proc->pid == last_pid) {
if (++ last_pid >= next_safe) {
if (last_pid >= MAX_PID) {
last_pid = 1;
}
next_safe = MAX_PID;
goto repeat;
}
}
else if (proc->pid > last_pid && next_safe > proc->pid) {
next_safe = proc->pid;
}
}
}
return last_pid;
}
// proc_run - make process "proc" running on cpu
// NOTE: before call switch_to, should load base addr of "proc"'s new PDT
void
proc_run(struct proc_struct *proc) {
if (proc != current) {
bool intr_flag;
struct proc_struct *prev = current, *next = proc;
local_intr_save(intr_flag);
{
current = proc;
load_esp0(next->kstack + KSTACKSIZE);
lcr3(next->cr3);
switch_to(&(prev->context), &(next->context));
}
local_intr_restore(intr_flag);
}
}
// forkret -- the first kernel entry point of a new thread/process
// NOTE: the addr of forkret is setted in copy_thread function
// after switch_to, the current proc will execute here.
static void
forkret(void) {
forkrets(current->tf);
}
// hash_proc - add proc into proc hash_list
static void
hash_proc(struct proc_struct *proc) {
list_add(hash_list + pid_hashfn(proc->pid), &(proc->hash_link));
}
// find_proc - find proc frome proc hash_list according to pid
struct proc_struct *
find_proc(int pid) {
if (0 < pid && pid < MAX_PID) {
list_entry_t *list = hash_list + pid_hashfn(pid), *le = list;
while ((le = list_next(le)) != list) {
struct proc_struct *proc = le2proc(le, hash_link);
if (proc->pid == pid) {
return proc;
}
}
}
return NULL;
}
// kernel_thread - create a kernel thread using "fn" function
// NOTE: the contents of temp trapframe tf will be copied to
// proc->tf in do_fork-->copy_thread function
int
kernel_thread(int (*fn)(void *), void *arg, uint32_t clone_flags) {
struct trapframe tf;
memset(&tf, 0, sizeof(struct trapframe));
tf.tf_cs = KERNEL_CS;
tf.tf_ds = tf.tf_es = tf.tf_ss = KERNEL_DS;
tf.tf_regs.reg_ebx = (uint32_t)fn;
tf.tf_regs.reg_edx = (uint32_t)arg;
tf.tf_eip = (uint32_t)kernel_thread_entry;
return do_fork(clone_flags | CLONE_VM, 0, &tf);
}
// setup_kstack - alloc pages with size KSTACKPAGE as process kernel stack
static int
setup_kstack(struct proc_struct *proc) {
struct Page *page = alloc_pages(KSTACKPAGE);
if (page != NULL) {
proc->kstack = (uintptr_t)page2kva(page);
return 0;
}
return -E_NO_MEM;
}
// put_kstack - free the memory space of process kernel stack
static void
put_kstack(struct proc_struct *proc) {
free_pages(kva2page((void *)(proc->kstack)), KSTACKPAGE);
}
// copy_mm - process "proc" duplicate OR share process "current"'s mm according clone_flags
// - if clone_flags & CLONE_VM, then "share" ; else "duplicate"
static int
copy_mm(uint32_t clone_flags, struct proc_struct *proc) {
assert(current->mm == NULL);
/* do nothing in this project */
return 0;
}
// copy_thread - setup the trapframe on the process's kernel stack top and
// - setup the kernel entry point and stack of process
static void
copy_thread(struct proc_struct *proc, uintptr_t esp, struct trapframe *tf) {
proc->tf = (struct trapframe *)(proc->kstack + KSTACKSIZE) - 1;
*(proc->tf) = *tf;
proc->tf->tf_regs.reg_eax = 0;
proc->tf->tf_esp = esp;
proc->tf->tf_eflags |= FL_IF;
proc->context.eip = (uintptr_t)forkret;
proc->context.esp = (uintptr_t)(proc->tf);
}
/* do_fork - parent process for a new child process
* @clone_flags: used to guide how to clone the child process
* @stack: the parent's user stack pointer. if stack==0, It means to fork a kernel thread.
* @tf: the trapframe info, which will be copied to child process's proc->tf
*/
int
do_fork(uint32_t clone_flags, uintptr_t stack, struct trapframe *tf) {
int ret = -E_NO_FREE_PROC;
struct proc_struct *proc;
if (nr_process >= MAX_PROCESS) {
goto fork_out;
}
ret = -E_NO_MEM;
//LAB4:EXERCISE2 YOUR CODE
/*
* Some Useful MACROs, Functions and DEFINEs, you can use them in below implementation.
* MACROs or Functions:
* alloc_proc: create a proc struct and init fields (lab4:exercise1)
* setup_kstack: alloc pages with size KSTACKPAGE as process kernel stack
* copy_mm: process "proc" duplicate OR share process "current"'s mm according clone_flags
* if clone_flags & CLONE_VM, then "share" ; else "duplicate"
* copy_thread: setup the trapframe on the process's kernel stack top and
* setup the kernel entry point and stack of process
* hash_proc: add proc into proc hash_list
* get_pid: alloc a unique pid for process
* wakeup_proc: set proc->state = PROC_RUNNABLE
* VARIABLES:
* proc_list: the process set's list
* nr_process: the number of process set
*/
// 1. call alloc_proc to allocate a proc_struct
// 2. call setup_kstack to allocate a kernel stack for child process
// 3. call copy_mm to dup OR share mm according clone_flag
// 4. call copy_thread to setup tf & context in proc_struct
// 5. insert proc_struct into hash_list && proc_list
// 6. call wakeup_proc to make the new child process RUNNABLE
// 7. set ret vaule using child proc's pid
if ((proc = alloc_proc()) == NULL) {
goto fork_out;
}
proc->parent = current;
if (setup_kstack(proc) != 0) {
goto bad_fork_cleanup_proc;
}
if (copy_mm(clone_flags, proc) != 0) {
goto bad_fork_cleanup_kstack;
}
copy_thread(proc, stack, tf);
bool intr_flag;
local_intr_save(intr_flag);
{
proc->pid = get_pid();
hash_proc(proc);
list_add(&proc_list, &(proc->list_link));
nr_process ++;
}
local_intr_restore(intr_flag);
wakeup_proc(proc);
ret = proc->pid;
fork_out:
return ret;
bad_fork_cleanup_kstack:
put_kstack(proc);
bad_fork_cleanup_proc:
kfree(proc);
goto fork_out;
}
// do_exit - called by sys_exit
// 1. call exit_mmap & put_pgdir & mm_destroy to free the almost all memory space of process
// 2. set process' state as PROC_ZOMBIE, then call wakeup_proc(parent) to ask parent reclaim itself.
// 3. call scheduler to switch to other process
int
do_exit(int error_code) {
panic("process exit!!.\n");
}
// init_main - the second kernel thread used to create user_main kernel threads
static int
init_main(void *arg) {
cprintf("this initproc, pid = %d, name = \"%s\"\n", current->pid, get_proc_name(current));
cprintf("To U: \"%s\".\n", (const char *)arg);
cprintf("To U: \"en.., Bye, Bye. :)\"\n");
return 0;
}
// proc_init - set up the first kernel thread idleproc "idle" by itself and
// - create the second kernel thread init_main
void
proc_init(void) {
int i;
list_init(&proc_list);
for (i = 0; i < HASH_LIST_SIZE; i ++) {
list_init(hash_list + i);
}
if ((idleproc = alloc_proc()) == NULL) {
panic("cannot alloc idleproc.\n");
}
idleproc->pid = 0;
idleproc->state = PROC_RUNNABLE;
idleproc->kstack = (uintptr_t)bootstack;
idleproc->need_resched = 1;
set_proc_name(idleproc, "idle");
nr_process ++;
current = idleproc;
int pid = kernel_thread(init_main, "Hello world!!", 0);
if (pid <= 0) {
panic("create init_main failed.\n");
}
initproc = find_proc(pid);
set_proc_name(initproc, "init");
assert(idleproc != NULL && idleproc->pid == 0);
assert(initproc != NULL && initproc->pid == 1);
}
// cpu_idle - at the end of kern_init, the first kernel thread idleproc will do below works
void
cpu_idle(void) {
while (1) {
if (current->need_resched) {
schedule();
}
}
}

View File

@ -0,0 +1,8 @@
.section __TEXT,__text
.globl start
start:
mov $0x1, %eax
push $0x0
call _syscall
_syscall:
int $0x80

View File

@ -0,0 +1,30 @@
.text
.globl switch_to
switch_to: # switch_to(from, to)
# save from's registers
movl 4(%esp), %eax # eax points to from
popl 0(%eax) # save eip !popl
movl %esp, 4(%eax)
movl %ebx, 8(%eax)
movl %ecx, 12(%eax)
movl %edx, 16(%eax)
movl %esi, 20(%eax)
movl %edi, 24(%eax)
movl %ebp, 28(%eax)
# restore to's registers
movl 4(%esp), %eax # not 8(%esp): popped return address already
# eax now points to to
movl 28(%eax), %ebp
movl 24(%eax), %edi
movl 20(%eax), %esi
movl 16(%eax), %edx
movl 12(%eax), %ecx
movl 8(%eax), %ebx
movl 4(%eax), %esp
pushl 0(%eax) # push eip
ret