PA2.1 运行dumy
PA2.1实现dumy
- 实现思路
- 实验过程
- 修改opcode_table数组
- 修改rtl.h文件
- 实现对应的操作
- 实验结果
实现思路
在进行代码编写之前,最重要的就是阅读实验手册,确保自己真的理解了实验手册中的内容,再下手也不迟,正所谓磨刀不误砍柴工。PA2实验对我来说还是有一点点的新奇,因为自己并没有接触过编译,所幸自己对计算机组成原理有一点的学习,知道指令的执行和操作过程,理解起来也就变的容易很多啦。
首先,我先根据实验手册中的指示,阅读dumy-x86-nemu.txt文件,弄清楚自己需要实现的指令及指令代码。
00100000 <_start>: 100000: bd 00 00 00 00 mov $0x0,%ebp100005: bc 00 7c 00 00 mov $0x7c00,%esp10000a: e8 01 00 00 00 call 100010 <_trm_init>10000f: 90 nop 00100010 <_trm_init>:100010: 55 push %ebp100011: 89 e5 mov %esp,%ebp100013: 83 ec 08 sub $0x8,%esp100016: e8 05 00 00 00 call 100020 <main>10001b: d6 (bad) 10001c: eb fe jmp 10001c <_trm_init+0xc>10001e: 66 90 xchg %ax,%ax00100020 <main>:100020: 55 push %ebp100021: 89 e5 mov %esp,%ebp100023: 31 c0 xor %eax,%eax100025: 5d pop %ebp100026: 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画流程图。。有点丑,以后会慢慢改进的。。)
实验过程
修改opcode_table数组
首先在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),
修改rtl.h文件
- push和pop操作
按i386手册和框架中给出的提示完成入栈和出栈的操作。
static inline void rtl_push(const rtlreg_t* src1) {// esp <- esp - 4rtl_subi(&cpu.esp,&cpu.esp,4);// M[esp] <- src1rtl_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;
}
实现对应的操作
- call指令
CALL:读取要压栈的eip值,然后用rtl_push压栈,然后设置跳转。
make_EHelper(call) { // the target address is calculated at the decode stage// Don't forget to add push eiprtl_push(eip); rtl_j(decoding.jmp_eip); print_asm("call %x", decoding.jmp_eip);
}
- push和pop指令
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);
}
- sub指令(参考sbb指令)
在实现sub指令前需要写eflags结构体(这个根据i386进行编写即可。)
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 = 0rtl_update_ZFSF(&id_dest->val, id_dest->width);print_asm_template2(xor);
}
- ret指令
make_EHelper(ret) { rtl_pop(&decoding.jmp_eip);rtl_j(decoding.jmp_eip);print_asm("ret");
}
实验结果
PA2.1 运行dumy相关推荐
- c语言正则表达式_CS143:编译原理|PA2:正则表达式和词法分析
本文使用 Zhihu On VSCode 创作并发布 这是本人实现斯坦福CS143变编程作业的笔记,对应第二次作业PA2.有关文章目录.环境搭建和一些说明请看第一篇:CS143:编译原理 | 环境搭建 ...
- PA2.2 PA2.3
PA2.2 讲义中的问题 堆和栈在哪里? 首先明确什么是堆和栈: 栈(stack):是自动分配变量,以及函数调用所使用的一些空间(所谓的局部变量),地址由高向低减少; 堆(heap):由malloc, ...
- Git 教程 - Git 基本用法
Git 是当前最流行的版本控制程序之一,文本包含了 Git 的一些基本用法 创建 git 仓库 初始化 git 仓库 mkdir project # 创建项目目录 cd project # 进入 ...
- 4、Lctech Pi(F1C200S)linux5.7.1移植在RAM运行修改默认调试串口为uart1(CherryPi,Mangopi,F1C100S)
本次主要参考: http://nano.lichee.pro/build_sys/bootargs.html https://wiki.sipeed.com/soft/Lichee/zh/Nano-D ...
- 计算机组成原理实验---PA实验PA2.22.3
目录 文章目录 目录 思考题 1.什么是 API 2.AM 属于硬件还是软件? 3.堆和栈在哪里? 4.回忆运行过程 5.神奇的`eflags` 6.这是巧合吗? 7.nemu的本质 8.设备是如何工 ...
- NEMU PA2实验思路
PA2实验思路 版权归zzy所有,不许外传! 本文主要是提供PA2思路,为了避免踩了一堆坑而浪费时间.若想copy代码请移步他处,本文仅供学习交流用,谢谢! 阅读前请确保仔细阅读了PA2实验指导书的有 ...
- 南航 PA2.2PA2.3
目录 思考题 1.什么是 API 2.AM 属于硬件还是软件? 3.堆和栈在哪⾥? 4.回忆运⾏过程 5.神奇的eflags(2) 6.这是巧合吗? 7.nemu的本质 8.设备是如何⼯作的? 9. ...
- spring boot项目 中止运行 最常用的几种方法
spring boot项目 中止运行 最常用的几种方法: 1. 调用接口,停止应用上下文 @RestController public class ShutdownController impleme ...
- Docker安装Apache与运行简单的web服务——httpd helloworld
Docker运行简单的web服务--httpd helloworld目录[阅读时间:约5分钟] 一.Docker简介 二.Docker的安装与配置[CentOS环境] 三.Docker运行简单的web ...
最新文章
- AI一分钟 | 搜狗王小川:今年重点战略是输入法升级和发展机器翻译;北京无人驾驶试验场下半年正式运营
- 松开手,你可以拥有更多
- STL中算法锦集(四)
- java kafka 多线程消费
- html如何播放h264视频,浏览器 – 我如何播放H264视频?
- 幼儿课外活动游戏_泰国清迈大小学校介绍 --【Little Star小星星幼儿园】
- JAVA分布式篇3——Dubbo
- ViewSwitcher用法浅析
- vue表格刷新数据_Vue.js的列表数据的同步更新方法
- 为什么我们拒绝使用 Docker
- Revit API切换三维视图
- DID 起步:图说去中心化身份 | ArcBlock 博客
- DOS的net命令详解
- 轻松打造自己的站内搜索引擎
- kubernetes入门之Downward API
- 花 3 分钟时间了解技术人应具备的思维能力 - 抽象
- 某猫电影 css 加密解决方案
- 线路负载及故障检测装置(2019全国大学生电子设计大赛C题:国家级一等奖)
- IE8浏览器Silverlight已被阻止解决办法
- 工具总结篇——vault
热门文章
- JavaScript语法糖的简析
- Elasticsearch和PHP
- DeFi收益来源全面概述
- NVIDIA Jetson 刷机大全
- java计算机毕业设计民宿运营管理网站源码+系统+mysql数据库+lw文档+部署
- Linux磁盘管理:lvcreate 常用命令
- python中nonlocal是什么意思_Python中的global和nonlocal
- 【redis6】redis6.2版本windows下载
- win10系统改变文本的默认打开方式
- 小鹏飞行汽车完成海外公开首飞;统一充电接口或让苹果每年损失百亿;Linus电脑内存问题致Linux 6.1补丁合并推迟|极客头条...