这个月身体挺疲惫的,nemu的进度也不是特别好,到北京还需要面对租房和学校的琐事,希望7月会好起来。
过去一个月在做nemu时候发现函数指针掌握的并不是特别好,索性重新复习下。
函数指针声明:
typedef int (*fun_ptr)(int,int); // 声明一个指向同样参数、返回值的函数指针类型
#include <stdio.h>
int max(int x, int y){
return x > y ? x : y;
}
int main(void){
/* p 是函数指针 */
int (* p)(int, int) = & max; // &可以省略
int a, b, c, d;
printf("请输入三个数字:");
scanf("%d %d %d", & a, & b, & c);
/* 与直接用函数等价,d = max(max(a, b), c) */
d = p(p(a, b), c);
printf("最大的数字是: %d\n", d);
return 0;
}
函数指针和普通指针区别不大,个人认为最大区别就是回调函数,也是nemu中经常用到的。
这里用知乎的一句话来解释:你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。
可以这样理解,号码就是回调函数的名称,手机就是函数指针,有手机有了号码,就可以进行回调
用代码来举例就是这样:
#include <stdio.h>
// 回调函数a
void callback_a(int var_a){
printf("Call callback_a, var: %d\n\n", var_a);
}
// 回调函数b
void callback_b(int var_b){
printf("Call callback_b, var: %d\n\n", var_b);
}
// 回调动作
void callback_act(int x, void (*callback) (int var)){
printf("Call callback_act, var_x: %d\n\n", x);
callback(x);
}
void main(){
int a = 1, b = 2;
callback_act(a, callback_a);
callback_act(b, callback_b);
printf("Main program has done.");
}
输出:
➜ ~ ./func
call callback_action,var_x:1
call callback_a function,var: 1
call callback_action,var_x:2
call callback_b function,var: 2
ysyx日记
在NPC实现异常处理的时候需要缕一下思路,索性就在这里记录一下了。首先我们要清楚自陷的机理,ecall执行后,首先我们的mcause和mepc寄存器被赋值为状态编码和当前的pc值。而后下一步执行mtvec寄存器中的值,这里mtvec寄存器已经被存放了__am_asm_trap的地址。所以ecall后就会执行__am_asm_trap.具体就是把当前寄存器入栈,而后开始跳转__am_irq_handle函数,这个函数就是对事件进行赋值,比如说我们这里根据寄存器状态赋值为EVENT_YIELD,同时也有其他的事件例如EVENT_ERROR等。而后return回__asm_trap函数中,开始从栈中恢复寄存器。最后执行mret,下一条指令是mepc寄存器值,也就是在发生异常时的下一条指令(在__am_irq_handle中mepc已经被+4了)。至此异常处理结束了。
所以如果我想在npc中实现异常处理的话首先要实现4个csr寄存器,其次要实现ecall指令。
ecall的状态编码已经给定了就是0xb,再把mepc寄存器赋值当前的pc值,后next_pc就是mtvec的寄存器中的值了。接下来就是执行__am_asm_trap函数,这里不需要我们实现,其中csrrw和csrrs还是需要我们实现的。
csrrw :这里就是根据csr立即数的值来看,我这里准备用idu来解析出来csrimm,而后采用选择器把odata赋值为被选择的寄存器准备输出到ALU中。这个ALU的结果最后返回到CSR寄存器中。然后odata不需要处理直接存入寄存器中。
csrrs : 这里也是根据csr立即数的值来看,然后把odata输入到ALU中和src1进行或运算,再把结果输入回csr寄存器中。然后把odata直接写到寄存器中。
mret 就是单纯的把next_pc设置为mepc的值咯
妈的debug一下午原来是汇编函数忘记加东西了!可恶!
标签:函数,int,六月,callback,寄存器,var,回调,小记 From: https://www.cnblogs.com/ink-bai/p/18275428