在lab3/lib/syscall.c里面有这样一段汇编:
这段汇编代码主要是将系统调用号存放在AX,参数a1,a2,a3,a4,a5分别放在DX,CX,BX,DI,SI当中。下面我们看一段代码:
trap_dispatch(struct Trapframe *tf) { // Handle processor exceptions. // LAB 3: Your code here. print_trapframe(tf); switch(tf->tf_trapno) { case T_DIVIDE:print_trapframe(tf);break; case T_DEBUG:print_trapframe(tf);break; case T_NMI:print_trapframe(tf);break; case T_BRKPT:monitor(tf);return; case T_OFLOW:print_trapframe(tf);break; case T_BOUND: case T_ILLOP: case T_DEVICE: case T_DBLFLT: case T_TSS: case T_SEGNP: case T_STACK: case T_GPFLT:print_trapframe(tf);break; case T_PGFLT:page_fault_handler(tf); return; case T_FPERR: case T_ALIGN: case T_MCHK: case T_SIMDERR:print_trapframe(tf);break; case T_SYSCALL: cprintf("enter syscall\n"); tf->tf_regs.reg_eax=syscall(tf->tf_regs.reg_eax, tf->tf_regs.reg_ebx, tf->tf_regs.reg_ecx, tf->tf_regs.reg_edx, tf->tf_regs.reg_edi, tf->tf_regs.reg_esi); return; default:break; } // Unexpected trap: The user process or the kernel has a bug. print_trapframe(tf); if (tf->tf_cs == GD_KT) panic("unhandled trap in kernel"); else { env_destroy(curenv); return; } }
这里并没没有输出hello,world!这就是因为我们前面所说的不一致而引起的,我们要将代码稍微改一下:将trap_distrap()函数里面case T_SYSCALL那里syscall()函数里面的参数tf->tf_regs.reg_ebx和tf->tf_regs.reg_edx对换一下。这里就输出了hello,world。
asm volatile("int %1\n" : “=a” (ret) : “i” (T_SYSCALL), “a” (num), “d” (a1), “c” (a2), “b” (a3), “D” (a4), “S” (a5), : “cc” ,“memory”);
在这个实验的PART A部分,我遇到了一个小小的问题,就是在env_run()当中,cr3的值变为零了。
代码如下:
void env_run(struct Env *e)
{
if(curenv != e){
curenv=e;
}
curenv->env_runs++;
cprintf("env_run cr3:%d\n", curenv->env_cr3);
lcr3(e->env_cr3);
env_pop_tf(&curenv->env_tf);
}
实际上这里是没有问题的,那么问题在哪里呢?我们找到env初始化的地方去。
代码如下:
void env_init(void)
{
int i;
LIST_INIT(&env_free_list);
for(i=0;i>NENV-1;i++)
{
envs[i].env_status=ENV_FREE;
envs[i].env_id=0;
LIST_INSERT_HEAD(&env_free_list,&envs[i],env_link);
}
}
然后就是env的分配:
int env_alloc(struct Env **newenv_store, envid_t parent_id)
{
int32_t generation;
int r;
struct Env *e;
if (!(e = LIST_FIRST(&env_free_list)))
return -E_NO_FREE_ENV;
if ((r = env_setup_vm(e)) < 0)
return r;
generation = (e->env_id + (1 << ENVGENSHIFT)) & ~(NENV - 1);
if (generation <= 0) // Don't create a negative env_id.
generation = 1 << ENVGENSHIFT;
e->env_id = generation | (e - envs);
e->env_parent_id = parent_id;
e->env_status = ENV_RUNNABLE;
e->env_runs = 0;
memset(&e->env_tf, 0, sizeof(e->env_tf)
e->env_tf.tf_ds = GD_UD | 3;
e->env_tf.tf_es = GD_UD | 3;
e->env_tf.tf_ss = GD_UD | 3;
e->env_tf.tf_esp = USTACKTOP;
e->env_tf.tf_cs = GD_UT | 3;
LIST_REMOVE(e, env_link);
*newenv_store = e;
cprintf("[%08x] new env %08x\n", curenv ? curenv->env_id : 0, e->env_id);
return 0;
}
这里我们知道新分配的env是插入到头结点后面的。所以我们分配的是env[NENV-1]的地址空间。但是实际上我们在env_run 中运行的是env[0],所以在env_run()函数中cr3变为零了。因此我们将初始化函数程序做如下修改:
void env_init(void)
{
int i;
LIST_INIT(&env_free_list);
for(i=NENV-1;i>=0;i--)
{
envs[i].env_status=ENV_FREE;
envs[i].env_id=0;
LIST_INSERT_HEAD(&env_free_list,&envs[i],env_link);
}
}