在进行代码编写之前,最重要的就是阅读实验手册,确保自己真的理解了实验手册中的内容,再下手也不迟,正所谓磨刀不误砍柴工。PA2实验对我来说还是有一点点的新奇,因为自己并没有接触过编译,所幸自己对计算机组成原理有一点的学习,知道指令的执行和操作过程,理解起来也就变的容易很多啦。
首先,我先根据实验手册中的指示,阅读dumy-x86-nemu.txt文件,弄清楚自己需要实现的指令及指令代码。
00100000 <_start>:
100000: bd 00 00 00 00 mov $0x0,%ebp
100005: bc 00 7c 00 00 mov $0x7c00,%esp
10000a: e8 01 00 00 00 call 100010 <_trm_init>
10000f: 90 nop
00100010 <_trm_init>:
100010: 55 push %ebp
100011: 89 e5 mov %esp,%ebp
100013: 83 ec 08 sub $0x8,%esp
100016: e8 05 00 00 00 call 100020
10001b: d6 (bad)
10001c: eb fe jmp 10001c <_trm_init+0xc>
10001e: 66 90 xchg %ax,%ax
00100020 :
100020: 55 push %ebp
100021: 89 e5 mov %esp,%ebp
100023: 31 c0 xor %eax,%eax
100025: 5d pop %ebp
100026: c3 ret
根据这个文件列出所需要实现的操作指令:
指令 | 编码 | Description |
---|---|---|
call | e8 | Call near, displacement relativeto next instruction |
push | 50 + rw /rb | Push register word/dword |
sub | 83 | Subtract sign-extended immediate byte from r/m word |
xor | 31 | Exclusive-OR dword register to r/m word/dword |
pop | 58+rw/rb | Pop top of stack into word/dword register |
ret | c3 | Return (near) to caller |
这里我介绍下我的debug之路
(第一次用markdown画流程图。。有点丑,以后会慢慢改进的。。)
首先在all-insert中添加所需要的指令名字:
make_EHelper(call); // control.c
make_EHelper(push); //data-mov.c
make_EHelper(sub); //arith.c
make_EHelper(xor); //logic.c
make_EHelper(pop); //data-mov.c
make_EHelper(ret); //control.c
修改opcode_table
/* 0x80, 0x81, 0x83 */
make_group(gp1,
EX(add), EX(or), EX(adc), EX(sbb),
EX(and), EX(sub),EX(xor), EX(cmp))
/* 0xe8 */ IDEX(J,call), IDEX(J,jmp), IDEX(I,jmp_rm), IDEXW(J,jmp,1),
/* 0x50 */ IDEX(r,push), IDEX(r,push), IDEX(r,push), IDEX(r,push),
/* 0x54 */ IDEX(r,push), IDEX(r,push), IDEX(r,push), IDEX(r,push),
/* 0x58 */ IDEX(r,pop), IDEX(r,pop), IDEX(r,pop), IDEX(r,pop),
/* 0x5c */ IDEX(r,pop), IDEX(r,pop), IDEX(r,pop), IDEX(r,pop),
/* 0x30 */ IDEXW(G2E,xor,1), IDEX(G2E,xor), IDEXW(E2G,xor,1),IDEX(E2G,xor),
/* 0x34 */ IDEXW(I2a,xor,1), IDEX(I2a,xor), EMPTY, EMPTY,
/* 0xc0 */ IDEXW(gp2_Ib2E, gp2, 1), IDEX(gp2_Ib2E, gp2), IDEXW(I,ret,2), EX(ret),
static inline void rtl_push(const rtlreg_t* src1) {
// esp <- esp - 4
rtl_subi(&cpu.esp,&cpu.esp,4);
// M[esp] <- src1
rtl_sm(&cpu.esp,src1,4);
}
static inline void rtl_pop(rtlreg_t* dest) {
// dest <- M[esp]
//*dest = vaddr_read(cpu.esp,4);
rtl_lm(dest,&cpu.esp,4);
// esp <- esp + 4
//cpu.esp += 4;
rtl_addi(&cpu.esp,&cpu.esp,4);
}
static inline void rtl_setrelopi(uint32_t relop, rtlreg_t *dest,
const rtlreg_t *src1, int imm) {
// dest <- (src1 relop imm ? 1 : 0)
rtl_li(&at, imm);
*dest = interpret_relop(relop, *src1, at);
}
static inline void rtl_msb(rtlreg_t* dest, const rtlreg_t* src1, int width) {
// dest <- src1[width * 8 - 1]
rtl_shri(dest, src1, width*8 - 1);
}
static inline void rtl_update_ZF(const rtlreg_t* result, int width) {
// eflags.ZF <- is_zero(result[width * 8 - 1 .. 0])
rtl_shli(&at, result, 32 - width * 8);
if(at == 0) cpu.eflags.ZF = 1;
else cpu.eflags.ZF = 0;
}
static inline void rtl_update_SF(const rtlreg_t* result, int width) {
// eflags.SF <- is_sign(result[width * 8 - 1 .. 0])
rtl_msb(&at, result, width);
cpu.eflags.SF = at;
}
make_EHelper(call) {
// the target address is calculated at the decode stage
// Don't forget to add push eip
rtl_push(eip);
rtl_j(decoding.jmp_eip);
print_asm("call %x", decoding.jmp_eip);
}
make_EHelper(push) {
rtl_push(&id_dest->val);
print_asm_template1(push);
}
make_EHelper(pop) {
rtl_pop(&id_src->val);
operand_write(id_dest,&id_src->val);
print_asm_template1(pop);
}
make_EHelper(sub) {
rtl_sub(&t2, &id_dest->val, &id_src->val);
rtl_setrelop(RELOP_LTU, &t3, &id_dest->val, &t2);
operand_write(id_dest, &t2);
rtl_update_ZFSF(&t2, id_dest->width);
rtl_setrelop(RELOP_LTU, &t0, &id_dest->val, &t2);
rtl_or(&t0, &t3, &t0);
rtl_set_CF(&t0);
rtl_xor(&t0, &id_dest->val, &id_src->val);
rtl_xor(&t1, &id_dest->val, &t2);
rtl_and(&t0, &t0, &t1);
rtl_msb(&t0, &t0, id_dest->width);
rtl_set_OF(&t0);
print_asm_template2(sub);
}
注意,还需要实现**static inline make_DopHelper(SI)**内的功能,这个按照注释实现就可以了。
4. xor指令
make_EHelper(xor) {
rtl_xor(&id_dest->val, &id_dest->val, &id_src->val);
operand_write(id_dest,&id_dest->val);
rtl_li(&t0,0);
rtl_set_CF(&t0);
rtl_set_OF(&t0);
//CF = OF = 0
rtl_update_ZFSF(&id_dest->val, id_dest->width);
print_asm_template2(xor);
}
make_EHelper(ret) {
rtl_pop(&decoding.jmp_eip);
rtl_j(decoding.jmp_eip);
print_asm("ret");
}