NEMU

本文最后更新于:19 天前

Record my programming process and give others some inspirations.

You can find source code from My github repo

/* But please do not just ctrl+c and ctrl+v */

And here is a very useful manual NEMU_gitbook

PA2

PA2要求我们在NEMU中实现部分X86指令集中的内容。

如果是第一次真正接触底层指令编写的话,一开始肯定是很茫然和无措的。(切身体会)

但别灰心,CS就是这样,只有不会才能提升嘛。那么就….开始!

三个关键宏

阅读指导书,会发现这样三个宏定义在实现新指令时都会被用到。

"nemu/include/cpu/helper.h"
/* All function defined with 'make_helper' return the length of the operation. */
#define make_helper(name) int name(swaddr_t eip)

"nemu/include/cpu/exec/helper.h"
#define make_helper_v(name) 
	make_helper(concat(name, _v)) { 
		return (ops_decoded.is_operand_size_16 ? concat(name, _w) : concat(name, _l)) (eip); \
	}
"nemu/include/cpu/exec/helper.h"
#define make_instr_helper(type) 
	make_helper(concat5(instr, _, type, _, SUFFIX)) { 
		return idex(eip, concat4(decode_, type, _, SUFFIX), do_execute); 
	}

这三个宏定义很巧妙地使用了函数指针和宏定义的配合。感兴趣可以了解一下

其中,make_helper函数的功能是声明一个函数,并且返回操作的长度

可以通过阅读代码知道,make_helper函数每次都要传入一个参数eip,返回一个int值。

make_helper_v函数的作用是用来确定一个函数的后缀

16位指令的话就+w(word,16bits),否则就+l(long word, 32bits);

make_instr_helper函数的作用就是确定函数的形式,并且进行译码、执行

其中 type 为指令的形式, 通过调用 idex() 函数来进行执行的译码和执行。

如果看不太懂没关系,下面来一个实例

mov_i2r_b指令的实现

"nemu/src/cpu/exec/date-mov/mov.h"
make_helper(mov_i2r_b);

"nemu/src/cpu/exec/date-mov/mov.c "
make_helper_v(mov_i2r)
    
"nemu/src/cpu/exec/date-mov/mov-template.h"
make_instr_helper(i2r)
    /*ignored the do_execute part*/

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!