关于我
欢迎来到我的博客!这里汇集了我对编程和技术的洞见和总结。本站内容分为几个主要类别,涵盖从具体技术实现到编程理念的广泛话题。
主要内容分类
- 项目工程:深入探讨技术的实现细节和理解。
- C/C++:围绕C/C++语言的技术点和编程技巧进行详细总结。
- 程序员哲学:分享程序员在职业生涯中应该具备的哲学理念和思考方式。
想要了解更多具体内容,您可以访问文章分类页面。
联系我
如果您有任何问题或想要交流,欢迎通过关于页面与我联系。
感谢您的阅读和支持,希望我的博客能为您的技术旅程带来帮助!
模拟器中关于指令ebreak的原理
ebreak指令是用于debugging.
转移控制给debugger或者monitor
其指令格式与其他指令格式不同:确实是其指令位都是0.
另一个作用:
作为断点点(breakpoint),可以由程序员或者debugger在程序中插入ebreak作为暂停处理器,使处理器的状态为stop.
这个ebreak指令是debugging,monite. 或者embeded microcontrollers or high-performance processors
ebreak指令被匹配上时,会调用NEMUTRAP宏.
NEMUTRAP宏callset_nemu_state function.
set_nemu_state function
first parameter is “state” NEMU_END
second parameter is current pc : “thispc”
third parameter is code : “code”
set nemu_state 变量中的state, halt_pc, halt_ret
为什么要有AM
AM提供的运行时环境,是一个简陋的环境,提供必要的API接口给程序.
操作系统提供的是一个全能的运行时环境,包括文件系统,cpu资源管理,性能测试等.
AM与操作系统的不同:还是需要依靠操作系统的编译环境.没有实现多线程调度,隔离进程,内存垃圾清理等任务.
运行时环境的抽象层次要比操作系统高点
关于程序编译在AMruntime_environment和GNU/Linux的区别
疑问一:为何程序默认编译之后,生成在GNU/Linux运行时环境运行的程序,和使用交叉编译生成在am提供的运行时环境的程序,两则不同.(从汇编代码角度考虑,当程序编译之后,生成的汇编代码不都是在.o文件中,我在nemu中实现对应的汇编指令不就好了)
程序从源码到可执行文件需要三步:预编译,编译,链接.
我们看到的汇编代码都是源码指令对应的直接代码,是可以在nemu中实现的.
但是在源码中所写的宏#include包含文件中的代码,并没有显示出来.
而是作为符号存储起来,用于在链接阶段与用到的库中的程序链接.
这里面运行时环境的代码我们并没有实现.
所以我们需要使用交叉编译.
并且我们的目标运行机器(nemu)的功能并没有提供比多线程,上下文切换的支持语句.所以,我们需要编译出更适合我们机器的代码.
如何实现hit good trap和bad trap
在执行am-kernels中的tests程序时:
没有实现的指令,会出现bad trap;
实现对的指令,出现good trap;
实现错的指令,有时候出现good trap有时候出现bad trap;
什么机制来触发bad trap?
如果程序执行的过程中,指令的实现是偏移的(结构上是正确的),也会出现bad trap
那么就有一个检查机制.
查看tests中的代码就会发现,有一个include预编译包含了trap.h文件.
每一个test程序都有检查机制(check函数).
这个check函数就在trap中定义.
这里的check函数,就在调用的地方,进行了检测,传入bool值,然后根据这个值,来调用halt函数.
__attribute__((noinline))的作用
在trap.h文件中,包含了am.h,klib.h,klib-macros.h文件
并且还这样定义了check函数:
1 | __attribute__((noinline)) |
这里的attribute是GCC编译器支持的一种属性,设置变量,结构体,函数的特定属性.
在这里是用的是,不要内联展开.
这样的check函数,便不会被编译器优化,在调用处展开,这样的话,利于监视跟踪.
关于__attribute__的使用.
放置位置,在不同的情景中,可以放置在不同的位置中:
例如: void fatal_error() __attribute__ ((deprecated));
klib.h文件
这里面定义了关于string.h/stdlib.h/stdio.h
在这里使用了extern “C”
使用原因:
在c++编译器中,由于重载的缘故,每一个函数的符号命名,都是由函数名和参数名一块进行确定最终命名的,这一过程是名称修饰.
在c编译器中,没有名称修饰.
所以c++编译的c函数,无法链接c对应的库,c编译器编译的c++代码,无法连接c++的库.
所以有了extern “C”
消除名称修饰.
halt函数
在trap.h文件中,包含了am.h文件
halt函数便是在am.h文件中声明的:
1 | void halt (int code) __attribute__((__noreturn__)); |
这里也使用了__attribute__((__noreturn__));
告诉编译器,这个函数是没有返回的.
halt函数是在abstract-machine/am/src
/native/trm.c文件
在这里,halt函数是调用了nemu-trap函数,将参数原封不动传入
在abstract-machine/am/src/platform/nemu/include/nemu.h文件中
定义了不同架构的nemu_trap宏
展开位asm的一个函数/宏
好,这里涉及到了内联汇编的知识.
内联汇编 asm
nemu_trap的最后功能代码是实现了一个汇编语句:mu a0, %0; ebreak
这个汇编语句的作用,以及参数的传导,在文档中已经有讲,但是这里要做的就是关于set_nemu_state函数的分析.见上.
实现了错误的指令,或者其他未实现的地方的处理
比如nemu中的INV指令,传入s->pc,在cpu.h文件中,定义INV宏
用于调用invalid_inst函数,而invalid_inst函数其实就是调用set_nemu_state函数,直接传参NEMU_ABORT, thispc, -1
而在此之前,就是将所有必要的信息printf出去.
If you like this blog or find it useful for you, you are welcome to comment on it. You are also welcome to share this blog, so that more people can participate in it. All the images used in the blog are my original works or AI works, if you want to take it,don't hesitate. Thank you !