收藏 分销(赏)

毕业设计论文-SVM-虚拟机设计.doc

上传人:可**** 文档编号:1903698 上传时间:2024-05-11 格式:DOC 页数:35 大小:320KB
下载 相关 举报
毕业设计论文-SVM-虚拟机设计.doc_第1页
第1页 / 共35页
毕业设计论文-SVM-虚拟机设计.doc_第2页
第2页 / 共35页
毕业设计论文-SVM-虚拟机设计.doc_第3页
第3页 / 共35页
毕业设计论文-SVM-虚拟机设计.doc_第4页
第4页 / 共35页
毕业设计论文-SVM-虚拟机设计.doc_第5页
第5页 / 共35页
点击查看更多>>
资源描述

1、 第 34 页 目录1 绪论11. 1课题背景及目的11.1.1为什么要设计虚拟机11.1.2虚拟机反对派观点31.2国内外研究状况31.3课题研究方法31.4论文构成及研究内容42 SVM 虚拟机设计42.1运形时系统与虚拟机42.2 SVM 虚拟机52.3 SVM虚拟机处理器设计62.3.1 机器处理器设计62.3.2 SVM虚拟机处理器设计82.4 SVM内存分配92.5 SVM内存寻址92.6 SVM 多字节存储方式102.7 SVM输入输出112.8 SVM 中断112.9 SVM 汇编器182.10 SVM 反汇编器202.11 SVM 调试器202.11.1概述202.11.2调

2、试技术212.11.3 SVM 调试器的实现212.12 建造运行时系统222.13 SVM 虚拟机的扩展223SVM 虚拟机运行时环境243.1SVM执行方式243.2 SVM调试方式254 程序设计处理294.1程序设计中的宏处理294.2程序设计中的异常处理30总 结33致 谢35参考文献361 绪论1. 1课题背景及目的1.1.1为什么要设计虚拟机就软件工业的发展趋势而言,一方面是需要运行在多种计算机平台之上的实用系统越来越多,另一方面是以网络为中心的计算情况越来越多,虚拟机也重新成为软件工业的一个潮流。基于单一操作系统的软件开发工具已经不能满足软件工程师的需要。面对杂乱的信息系统和日

3、新月异的技术发明,软件工程师们开始重新审视开发虚拟机的优点。编写虚拟机是软件开发项目的一种,它体现了一种使投资价值最大化的思路。为了从资源方面的投资得到最大的回报,企业都希望自己花钱开发出来的软件的使用期限能够尽可能地长。把软件包从一种平台移植到另一种平台的工作需要花费不小的成本,而且并不是所有的软件包都能够移植到所有的平台上去,软件包所能支持的平台种数是有限度的。大量事实表明,软件移植工作往往会变成一场噩梦。使用虚拟机就可以在一定程度上避免这类事情的发生。当遇到一种新硬件平台或者新操作系统的时候,唯一需要移植的应用级软件就是虚拟机本身1。1.1.2虚拟机反对派观点有不少人反对使用虚拟机,他们

4、的观点有许多种,其中最主要的就是虚拟机会降低程序的执行性能。他们认为,编译型语言如C语言是以计算机自身的机器码的形式执行的,因此会执行得更快些。但这种说法并不一定正确。纯粹的C+代码并不一定比由虚拟机执行的字节码(byte code)更快。程序的执行时间主要消耗在运行时库以及内核模式中断处理例程方面,只有当处理的代码是完全孤立且没有调用任何用户库或系统调用时(因为程序要等待系统的响应)才能百分之百肯定其机器码会执行得更快。对于企业应用级系统,虚拟级在可移植方面的优势足以弥补这些其实并慢不了多少的性能损失1。1.2国内外研究状况一个商业级的虚拟机实现是极其复杂的,一个开源虚拟机bochs 做得很

5、好,其2.0.2版在Win32平台下的有13万行源代码(C/C+)。能在其上运行minux(linux 前身),FreeDSB, Windows95,Windows NT 4.0等操作系统。另一种虚拟机有自己的指令集,它是针对一种语言来设计和实现的。比如JVM(JAVA virtual machine JAVA 虚拟机)。.NET平台。而由JVM所支持的JAVA语言,目前正得到广泛的应用。1.3课题研究方法一台虚拟机与一台真实存在的计算机的不同之处在于前者只是一个技术规范。这类技术规范由一系列规则构成,而软件工程师可以采用任何他自己认为适当的手段来实现这些规则。这就使虚拟机能够做到与具体的计算

6、机平台无关。对一台虚拟机来说,只要它能够遵从其技术规范里的各项规则,就可以存在于任何一种计算机平台上,就可以用任何一种计算机语言来编写1。我的毕业设计所做的虚拟机采用标准C/C+语言编写,在结构上模仿了8086计算机体系结构。1.4论文构成及研究内容本论文作为对虚拟机开发的一个尝试,实现的部分偏重于CPU也即指令执行部件。而对于虚拟机这个运行时系统的另一个很重要的部分中断处理,由于涉及面太广,故只是象征性的实现了INT 10H 0EH中断(向屏幕输出),INT 20H中断(退出程序)。我做的虚拟机取名为SVM(simple virual machine)简单的虚拟机。论文中将主要说明整个SVM

7、虚拟机的设计实现过程,由于涉及到编程语言C/C+,也参考了一些程序设计书上的内容,在文中一并写出来。(以后略)2 SVM 虚拟机设计2.1运形时系统与虚拟机运形时系统(run-time system)是各种计算机程序在其中得以执行的一个环境。运行时系统提供了程序在执行时所需要的一切东西。例如,运行时系统要负责为应用程序分配内存,把该应用程序加载到分配好的内存里,然后开始执行该程序中的指令。如果该程序通过调用系统调用要求位于底层的操作系统提供服务,该运行时系统还必须负责处理有关的服务请求。例如,如果应用程序需要进行文件I/O操作,运行时系统就必须向它提供一种与磁盘控制器进行通信并提供读写访问的机

8、制。运行时系统的种类有很多。对运行时系统进行分类的一个办法是把它们按执行程序指令的基本方式进行划分。对那些以处理其本身的机器码为指令的程序而言,某计算机的处理器和操作系统就构成了与之对应的运行时系统,处理器提供了一种执行指令的机制。CPU把编码为数值形式的指令从内存里取出并根据那些指令完成相应的动作,操作系统则实现了(由处理器和操作系统构成的)这个运行时系统的策略部分。CPU负责执行指令, 操作系统负责决定事情何时,何地发生。对那些用机器指令编写的程序来说,计算机本身就是一个运行时系统。程序的指令由物理CPU在机器级上执行,指令执行的具体过程由操作系统管理。这类运行时系涉及计算机硬件和软件。那

9、些指令不由物理处理器来直接执行的程序需要一个完全由软件构成的运行时系统。在这种情况下,程序的指令将由一台虚拟机来执行。虚拟机是类似于计算机的一个软件程序,它会像真正的处理器那样取出并执行程序指令,但两者的区别在于虚拟机的指令执行过程发生在软件级而不是硬件级,即指令是由软件而不是硬件执行的1。2.2 SVM 虚拟机SVM虚拟机是通过模拟硬件平台而实现的。 SVM采用8086指令集。这样可以省去一些建造虚拟机的重要步骤比如,指令集不用重建(事实上,我也没有能力去定义一个完备的指令集)。SVM虚拟机采用单任务方式,每次只运行一个程序。虚拟机总体结构如下:图2.1 虚拟机总体结构SVM 虚拟机源文件组

10、成:c8086.h 声明8086处理器类;c8086.cpp 实现8086处理器类;ram.h 声明内存类;ram .cpp 实现内存类;disasm.h 反汇编函数声明;disasm .cpp 反汇编函数定义;debug.h 调试器函数声明;debug.cpp 调试器函数定义;fileLoader.h com文件加载函数声明;fileLoader.cpp com文件加载函数定义;global.h 全局数据类型定义;test_CPU.cpp SVM测试程序主函数。编译执行环境:运行,开发平台:Windows 98 SE , Windows 2000 professional SP4编译器:Vi

11、sual C+ 6.0/7.0(VC是对标准C/C+支持很好的一个编译器)2.3 SVM虚拟机处理器设计2.3.1 机器处理器设计中央处理器可以实现为基于寄存器或者基于堆栈的机器。一个基于寄存器的处理器,如Intel 公司的Pentium芯片,有8个用来完成基本运算的32位寄存器。一个基于堆栈的处理器,如Harris半导体公司的RTX32P芯片,有两个用来完成基本运算的片上堆栈。基于堆栈的处理器在嵌入式系统中比较流行,这是因为这类处理器支持比较短小的程序,在资源有限的场合也能工作得很好。同时函数调用在基于堆栈的机器上完成得也更有效率,因为函数参数都已经被放到堆栈里去了。而在一台基于寄存器的机器

12、上,函数参数必须逐个收集并压入堆栈,这就需要做更多的工作。上下文切换在基于堆栈的机器上的开销也比较小。如果是在一台基于寄存器的机器上进行上下文切换,就必须把它所有的寄存器的状态都保存起来。对拥有大量寄存器的RISC体系结构来说,上下文切换是一个消耗内存的操作。基于堆栈的机器就不存在这种问题。基于堆栈的计算机可以为每个进程分别准备一个堆栈,切换上下文时只需变一下堆栈就行了。既然有这么多的优点,基于堆栈的机器为什么没有成为计算机体系结构的主流呢?这是因为基于寄存器的处理器有一个极其重要的优势:速度快。寄存器就在CPU的内部,如果是对保存在寄存器里的数据进行运算,那它的运算速度将是非常快的。Inte

13、l 公司在它新推出的64位处理器Itanium里安排了好几百个片上寄存器,目的就是为了让程序操作尽可能多地在芯片上执行。再看基于堆栈地处理器,它们的片上堆栈几乎总是会延伸到内存里去。这就造成了这样一种后果:即使执行的是一个面向堆栈的基本操作,处理器也不得不到内存里去读取数据。这就大大降低了基于堆栈的处理器的执行速度。并且基于寄存器的处理器比较容易调试(debug),因为指令的执行过程更清晰(一部分操作数在寄存器中,在运算完后还可以检查参与运算的数值是多少)1。表2.1 基于寄存器的处理器和基于寄存器的处理器的优缺点基于堆栈的处理器基于寄存器的处理器优点比较小的内存开销比较快的函数调用基本操作比

14、较快(整体性能更好)执行过程比较清晰(易于调试)缺点比较快的进程切换基本操作比较慢上下文切换时要消耗大量内存调用函数时要多做很多工作2.3.2 SVM虚拟机处理器设计由于虚拟机完全由软件构成,没有硬件设备,所以它不存在刚才提到的某些缺陷。与硬件处理器的分类相似,虚拟机也有基于堆栈和基于寄存器之分。JVM就是基于堆栈的。这可以使JAVA字节码文件很短。而我将SVM虚拟机的中央处理器实现为基于寄存器的机器。直接采用8086指令集。要知到,设计一个完备的指令集可不是一件简单的事,至少我还没有那种实力。SVM虚拟机的设计目标是能够运行原8086平台下的部分16位com程序(程序只能使用除去HLT,WA

15、IT,IN,OUT,LOCK,ESC的88条指令,并限制使用INT指令)。SVM虚拟机处理器的组成:寄存器SVM虚拟机有8个通用整数寄存器,4个段寄存器,一个指令指针,一个指令指针,一个标志寄存器(它有16位,但只使用其中的9位)。这些寄存器及其用途如图所示:表2.2寄存器及其用图AX = AHAL整数寄存器(累加器)BX = BHBL整数寄存器 (基数寄存器)CX = CHCL整数寄存器 (计数器)DX = DHDL整数寄存器 (数据寄存器)BP基址指针SP堆栈指针SI源变址寄存器DI目标变址寄存器CS代码段寄存器DS数据段寄存器SS堆栈段寄存器ES扩展段寄存器IP指令指针FLAG标志位其中

16、,AX,BX,CX,DX 都能划分为两个8位寄存器。一个用来保存低字节,一个用来保存高字节(如AX寄存器可以划分为AH 和 AL)。运算单元由C8086类(在C8086.C中)的成员函数实现。2.4 SVM内存分配SVM 虚拟机在启动时会请求分配1M字节的内存空间,内存空间有可能会到虚拟内存中去,因为没有对可用物理内存进行检查。但由于只能加载com程序,实际上只使用了其中的64KB字节。2.5 SVM内存寻址SVM 模拟8086处理器,选用20位的实模式的地址空间,内存中某个字节的地址时由两位16位数值指定的,这两个数值分别叫做“段地址”(segment address)和“偏移地址”(off

17、set address)。一个给定字节的内存地址是这样计算出来的:把16位段地址乘以16(即0x10),然后把结果与偏移地址相加。2.6 SVM 多字节存储方式多字节数据在内存中有两种存放方式:降序格式(big-endian)和升序格式(little-endian)。如果一个多字节数据的最高位字节存放在内存中的最低位地址,我们就说它采用的是降序记号。升序记号方式正好相反多字节数据的最低位字节降存放在内存中的最低地址。请看下面这个例子。假设有一个多字节值“0Xabcdef12”存放在内存中的某个地方(我们不妨假设从地址24处开始存放)。这个数据的降序和升序表示法如图所示:ABCDEF12降序存储

18、方式:24 25 26 2712EFCDAB升序存储方式: 24 25 26 27 图:多字节数据值在内存中的两种存放方式:降序和升序以降序方式表示的数据也称为“网络顺序”(network order)。这是因为TCP/IP等网络协议要求通过网络传输的信息都必须采用降序格式1。 SVM虚拟机的设计目标是执行DOS下的使用8086指令集的程序,故对多字节排列采用升序方式。2.7 SVM输入输出对于8086平台,它有两个指令可以用来把寄存器长度的数据读写到外设:IN 和OUTIN指令用来从某个I/O端口读入数据。OUT用来把某个数据写到某个I/O端口。I/O端口是被映射到某个外设或者外设的某个部件

19、的一个数字。端口号的范围是0到65535。由于对计算机里的I/O硬件进行设置需要考虑太多的细节,需要很长的时间去收集齐全外设的信息(工作原理,功能号,端口号等),所以,在实现SVM虚拟机的I/O时,我只能用软件来模拟实现I/O(还只能实现向屏幕输出单个字符)。输出 INT 0X10 功能号 0X0E,模拟实现。虽然在Win32下,用软件实现SVM虚拟机的I/O时,使用底层的系统调用(system call)能够获得更好的性能,这些操作更接近硬件,并且一般不提供缓冲功能(bufferring)或额外的格式化(formatting)。C语言标准的函数就是建立在系统调用层之上的(即封装具体平台下的底

20、层系统调用),它更侧重于功能而不是执行速度。但倚赖与C语言标准API对我来说好入手一些,同时,也利于对SVM虚拟机本身的移植。2.8 SVM 中断实模式下的中断处理通过置位/清零,FLAG的第10个比特位(如果下标从0开始计算,就是第9位),我们就能激活/禁止实模式下的软件中断。人们把这个标志位称为IF(interrupt flag中断标志)。IF标志可用两条指令进行置位或清除。STI指令用来对IF标志进行置位,从而使处理器能够对中断做出响应。CLI指令用来清除IF标志,从而使(大多数)中断都被屏蔽。软件中断是用INT指令产生的。每执行一条INT指令,就会产生一个软件中断。INT指令的操作数是

21、一个单字节的整数,人们把它称为“中断向量”(interrupt vector)。例如,用来处理第12个中断向量的指令就是“INT 12”。中断向量可以是0到255之间的任意整数。中断向量其实只是“中断向量表”(interrupt vector table ,IVT)的下标,IVT中的元素都是双字(4字节)数值。既然中断向量有256个可能的取值,IVT表的长度就是1024个字节。中断向量表从处理器地址空间的最底端开始,因此它将占据内存的第一个KB。IVT表中的每一个双字数据项包含着某个中断服务程序的段地址和偏移地址。偏移地址保存在第一个字节里,段地址保存在随后的第二个字里。中断下向量表的构造情况

22、如图所示:图2.2 中断下向量表的构造图处理器在执行中断指令时将按如下步骤进行:1) 把FLAG寄存器压入堆栈2) 把CS寄存器压入堆栈3) 把IP寄存器压入堆栈(向量中断处理结束后将要执行的下一条指令)。4) 清除IF和TF标志位5) 根据中断向量找到对应的IVT数据项6) 把IVT中的段地址和偏移地址分别加载到CS 和 IP 寄存器里去。从效果上讲,这等于是让程序控制条转到中断服务程序,中断服务程序去做自己该做的事。为了让处理器回到一种“清醒”的状态,放到中断服务程序里的第一条指令应该是STI指令,这将唤醒处理器并使它能够再次接受中断请求。中断服务程序必须用IRET指令返回,IRET指令将

23、把以上步骤反过来执行。使程序路径能够正确地回到紧跟再刚才这条中断指令的下一条指令上去。具体来说,IRET指令将按以下步骤进行:1)把堆栈顶部的16位数值弹出到IP寄存器里去。2)把堆栈顶部的16位数值弹出到CS寄存器里去。3)把堆栈顶部的16位数值弹出到FLAG寄存器里去。SVM虚拟机将简化以上硬件中断处理的过程。它使用软件模拟的方式实现BIOS中断。SVM虚拟既需要依赖宿主操作系统提供诸如输入输出之类的基本服务。让自己游离于硬件通信细节之外。SVM虚拟即让宿主操作系统作为之给予精简设备之间的中间人,不直接与硬件发生纠缠(实事上在Win32下,如果不是驱动程序,也不可能有ring0级权限去访问

24、硬件)。也就是说,宿主操作系统将代表虚拟机来请求各种底层的操作细节。每一中操作系统都会提供一些人们称之为“系统调用“(system call)的基本函数,这些系统调用将负责管理机算计的可用资源调用。系统调用就像是一些原子元素,它们的各种组合构成了操作系统这个宇宙中的一切事务。任何一个操作系统命令或任何一个用户程序都可以分解为一系列系统调用。系统调用一般都处于非常底层的位置。它们的操作只能用特定机器的硬件语言来描述。换句话说,系统调用大都是用汇编语言写的。以汇编语言来编写系统调用的原因并不是出于速度方面的考虑执行速度方面的边界效应与成千上万行汇编代码所形成的思维复杂性并不成比例。一会便于演变歇息

25、同调用的真正原因是有些事情你只能用汇编语言来做。系统调用的输入输出参数还必须通过特定的机器寄存器来指定。为了降低复杂性,系统工程师会尽量把与硬件直接相关的汇编代码的操作系统的底层操作隔离开来。软件开发人员再用C/C+对汇编代码进行打包以使之更容易使用。把机器操作归结为一整套系统调用的做法是非常有远见的。但这绝不是对机器操作的抽象至少有两个层次来隔离核心级汇编语言例程的系统调用以及来封装系统调用的函数库调用。如图所示:图2.3系统层次图 C程序设计语言的标准函数库是这种抽象归纳的经典示例。比如putchar()函数。各种版本的标准函数库实现大都以更通用的putc()函数定义putchar()函数

26、,putc()用来把一个字符写到一个给定的输出流去。就putchar()函数而言,它的输出流被规定为标准输出(stdout)。#define putchar(c) putc(c, stdout)因此,要想了解putchar(),必须先把putc()搞清楚:int putc(int ch, FILE *stream)int ret;ret = write(stream, &ch, 1);if (ret != 1) return (EOF);elsereturn (ch);putc()函数又用到了一个名为write()的系统调用,这种嵌套结构的特点是:越接近硬件,函数或例程的功能就越通用,越基本。

27、/*stream = output stream to write to buffer = buffer of bytes to write to streamnbytes = number of bytes to writereturns = number of bytes written to stream*/int write(FILE *stream, void *buffer, int nbytes)struct call_struct;call_struct.type = FILE_SYSTEM;call_struct.subtype = BUFF_OUTPUT;call_stru

28、ct.param1 = (long)stream;call_struct.param2 =(long)buffer;call_struct.param3=nbytes;asmMOV ECX,USE_LIBRARYLEA EAX,call_structINT SYSTEM_CALLwrite()函数实际上是一个二传手,它将把球在传给一个名为system_call的系统调用通道,一般地,操作系统只有一个对系统调用请求进行集中分配的机制,而这是很有必要的。这是因为,系统调用通常都是用软件中断实现的,而产生软件中断的办法只有一种(如在Intel平台上使用的INT指令)。换句话说,系统调用其实就是一系列

29、相同的基本指令编写出不同的变化组合。从上图中可以看出,系统调用通道是用户级函数库与各种系统调用之间的一条必经之路。在具备内存保护机制的操作机制的操作系统里,系统调用通道将是用户执行各种系统调用的唯一途径,除此之外,没有第二条路可走。这就使计算机的运行状态产生了“内河模式”(kernel mode)和“用户模式”(user mode)之分。当CPU正在执行的指令属于某个系统调用时,我们就说它运行在内核模式;当计算机正在执行的指令属于某个库函数或者属于用户编写出来的某个函数时,我们就说它运行在用户模式。在某种程度上,我们可以把操作系统看作是由它的全体系统调用所构成的一个集合,那些系统调用就好比是操

30、作系统的签名。但系统调用接口摒不能把操作系统完全的定义下来,而是由其系统调用接口以及那些系统调用的具体实现方法所定义的1。SVM虚拟机的中断调用结构如下图:图2.4 SVM虚拟机中断调用结构:2.9 SVM 汇编器汇编语言在4月份对C8086类的测试中(单元测试,即单独测试一个个的指令执行单元),我是以手工方式建立机器码文件。但是,如果是面对大量的机器码编程,需要考虑周全的琐碎细节,这只能使人感到力不从心。不用手工方式来建立机器码可执行文件的办法是存在的。具体地说,用一种汇编语言来编写可执行文件是完全能够做到的。汇编语言是一种底层程序设计语言。为了更好的理解这句话的含义,我们必须先搞清楚几个概

31、念。“程序设计语言”是一种能够用来准确地写出程序的符号系统。程序设计语言通过他们的语法(syntax,该语言所能使用的符号以及这些符号的使用规则)和语义(semantics,语言符号所代表的含义)得到定义1 。程序设计语言的符号化语句不会产生歧义,这是他们与数学语句的相似之处。但程序设计语言的符号化语句却不必非得解析成“真”或“假”,这是它们与数学语句的不同之处1。语言的语法可以通过一套名为“上下文无关文法”(context-free grammar)的规则集合做出正规定义。程序设计去眼大都采用一种名为“巴科斯诺尔范式”(Backas-Naur form,BNF)的记号来表示它们的语法规则。语

32、言的寓意很难用含义精确的逻辑符号来描述1。“汇编语言”是一种程序设计语言,它直接把符号化的助记符映射为机器指令,机器指令和助记符之间的映射结果几乎是一对一的关系1。1110 1001 0000 1111 0000 0000 直接映射为:JMP 0012汇编语言里还提供有“宏指令”(macro directivec)。洪指令用来经以各种符号,这些符号可以代表内存地址,数值常数或一组机器指令。汇编语言中的宏指令的用法与C程序设计语言的情况基本相同1。一般来说,用汇编语言写成的源文件可以被一种人们称为“汇编器”(assembler)的开发工具翻译或者汇编为机器码可执行文件。汇编器能够体程序员完成内存

33、地址,偏移量和其他琐碎的安排记录工作1。程序设计语言是对处理器指令的抽象,我们可以根据这种抽象的高低层次来对它们进行分类。低级语言如汇编语言的特征与机器指令有相当直接的对应关系。汇编语言中的一条语句通常直接对应一条机器指令。而高级语言如BASIC与机器操作细节的距离则相当遥远,BASIC语言中的一条语句往往相当于很多条机器指令。中级语言如C语言则用使具备执行低级操作和高级操作的能力1。汇编器的设计将要涉及一些将当复杂的数据结构。好在有NASM,MASM等汇编器存在。因为汇编器比虚拟机要复杂很多。SVM 虚拟机采用的是8086指令集,这样就可以用已有的支持8086的汇编器,如NASM , TAS

34、M, MASM等。我使用的是NASM,用来编译com文件的格式是:C:program filesnasm test.asm f bin o -f 用来生成com文件; -o 用来指定生成的文件明。2.10 SVM 反汇编器作为SVM虚拟机调试器的组件之一,为便于管理代码,从调试器代码中独立了出来。SVM反汇编器简单地将机器码翻译为对应的汇编源程序,其结构和C8086类很相似,只是在处理机器码时不执行罢了。2.11 SVM 调试器2.11.1概述“调试器”(debugger)是一种软件开发工具, 它能让一个程序的执行路径暂停下来以便人们查看和修改概进程的机器状态。调试器就像是一个特殊的实验室,你

35、可以在里面运行和分析程序,看它在执行时到底在干些什么。例如,在某程序执行路径上的某个特定地点,你可以把一切都冻结起来,然后查看一下寄存器或内存区间的情况以检查某个给定变量的值。有些不易发现的程序漏洞只有在这类环境下才有可能被捕获和分析1。调试器又分为两个基本类型机器级调试器源码级调试器划分这两类调试器的标准是它们所管理的”指令粒度”(granularity of instructions)。机器级调试器处理的指令是二进制编码形式的底层机器指令。它使你能够观察到计算机最底层,最基本的操作情况。机器级调试器是最后一道防线,一般用来分析已经成品化了的程序1。源代码级的调试器处理的指令是高级程序设计语

36、言的语句。源代码级调试器使我们能够在程序设计语言的框架里追踪程序的执行路径。一般来说,源代码级调试器要比机器级调试器更容易使用,因为工程师们用不着再把精力浪费在大量的机器细节上,源代码级调试器都已经替他们照顾到了1。2.11.2调试技术为了提供基本调试功能,各种调试器都使用了两种基本技术:断点单步执行(1)断点“断点”(bread point )是一种特殊类型的机器指令, 在使用中,它们将插入到程序的正文段(text segment)里。断点既可以在程序运行时被插入既把断点放到某个进程的内存映像里去,也可以在编译时插入即把断点放到可执行文件里去。不论采用的是哪种方法,断点的作用都是一样的:让处

37、理器暂停某个任务的执行并把程序控制转交给调试器,以便用户查看和修改该任务的机器状态1。(2)单步执行“单步执行”(simle-step excution)是处理器的一种执行模式,在这种模式里,处理器每执行完一条语句,就会把程序控制转交给调试器。在单步执行模式下,调试器能够一条指令一条指令地追踪进程的执行路径。一般情况下,用在在接近某个预定代码区域的某个地方设置一个断点。当执行路径到达这个断点并把程序控制转交给调试器之后,用户再以单步执行方式通过这个预定代码区域,看该代码区域里会发生什么事情1。2.11.3 SVM 调试器的实现SVM 调试器是一个机器级调试器。仅仅作为一个尝试,SVM 调试器很

38、简陋,只提供了几个服务。不支持断点,寄存器修改等功能。该调试器的功能见SVM虚拟机调试器的使用。2.12 建造运行时系统建造一个虚拟机运行时系统的步骤大体上如下图:图2.5 建造虚拟机网络图2.13 SVM 虚拟机的扩展到此,SVM 虚拟机的功能仍然是很不完善的,由于初始设计的原因,要对其进行扩展有可能要重新设计整个程序的结构,尤其是处理器对调试器的支持部分。SVM 虚拟机可以扩展的方面还有很多,还可以做虚拟设备,扩展指令集,加载NE 文件,实现IN,OUT 等涉及硬件的指令,实现更多的BIOS中断。其中BIOS中断又有两种实现方式用软件模拟实现,或在建好虚设备的基础上载入一段BIOS程序。关

39、于调试器的扩展,原本调试器的功能可以更强的,比如指定反汇编的位置,设置断点等。但对于命令行的处理太过繁琐,需要对参数进行严格的检查。时间不够,我也就没有做了。而调试器中的相关接口函数确实是提供了指令定位的功能。还可以加入更多的防错处理使得SVM虚拟机更健壮。当然,扩展是在16位数据的基础上的,若是要建造32位的虚拟机,SVM整个都要改,不只是表面上指令的操作数位数不同了,IA32相对于16体系结构变化很大,出现了3种指令执行模式:实模式,保护模式,虚拟86模式。技术的发展是趋于完善,复杂的,SVM只是一个尝试。对于SVM,要改成32位虚拟机,那就不叫扩展,而是重构了。目前,BOCHS虚拟机(一

40、个开源的虚拟机)在模拟32位硬件平台上就做得很好。 SVM 虚拟机运行时环境3.1SVM执行方式SVM虚拟机生命期图3.1 SVM 虚拟机生命期启动虚拟机C:Program filessvm 运行示例:在SVM下运行的结果在msdos下运行的结果图3.2 SVM运行图3.2 SVM调试方式进入调试方式c:program filessvm d-q 退出调试器(1) 显示存储单元内容D命令(Dump Command)-d从即将执行的地址开始, 显示80H个字节单元内容图3.3 显示内存单元上述显示内容分为三部分:左边是每一行存储单元的起始地址(段基值:偏移量);中间是16个字节单元,以两位十六进制

41、数显示其现行内容;右边是中间各字节单元用相应的ASCII码字符显示,如该单元数据是不可显示字符,使用“.“表示。(2)显示寄存器内容R命令(Register Command)-r图3.4 显示寄存器内容键入R后, CPU各寄存器内容全部显示出来。第二行后半部显示标志寄存器各标志位状态,且各标志位的复位(“0”状态)和置位(“1”状态)是用两个字符来表示的,如表所示;显示的第三行表示现在CS:IP指向的下面将要执行的指令。表3.1 标志寄存器个标志位的状态字符标志位置位复位益处位OFOVNV方向位DFDNUP中断位IFEIDI符号位SFNGPL零值位ZFZRNZ辅助进位位AFACNA奇偶位PFP

42、EPO进位位CFCYNC显示汇编语言指令(反汇编)U命令(Unassemble Command)在调试状态下运行程序是执行某内存区域的目标代码,为了知道执行的是什么指令,操作数的地址在哪里等,希望把目标代码“还原”为汇编语言指令(即源程序中指令),这个操作叫做反汇编。U命令从当前地址开始,显示32个字节目标代码的汇编语言指令。执行U命令后,屏幕显示示例如下:图3.5 反汇编输出(4)单步运行方式T命令(Trap Command)每次执行T命令,仅执行一条指令。每执行完一条指令后,就自动显示CPU中各寄存器和标志寄存器内容。并显示下一条即将执行的指令。T命令执行的显示示例如下:图3.6 跟踪方式

43、输出4 程序设计处理4.1程序设计中的宏处理C8086类由一个译指令成员函数和执行成员函数以及一些辅助成员函数组成。当一个指令执行时,译码成员函数对其第一个字节进行翻译,并选取相应的执行函数对指令进行处理。为了尽可能的提高指令的执行速度,我将执行成员函数及辅助成员函数全部声明为内联函数,以省去函数调用的开销。当然,最后的可执行文件要比基于函数的大很多。注:在各种类型的C 编译器里,函数调用总是会有一定的开销。调用一个函数通常需要把一些数值压入堆栈,把程序执行点切换到内存里的另一个地点,最后在从堆栈里弹出一些数值。避免这类开销的办法之一是把函数定义为宏(macro)。例如有一个函数,如果它会被频

44、繁地调用,为了节省函数调用过程中系统开销,我们可以把函数写成宏:#define abs(x) ( (x) = 0) ? (x) : -(x)这样,(通过预处理程序展开宏)我们每一次调用abs(x),譬如:int a = abs(-5);我们就相当于直接写:int a = ( (5) = 0) ? (5) : -(5);效率明显比编写一个函数然后调用它要好。但宏也不是万能的,它有很多不尽人意的方面,例如:int a = abs(5) + 1;/* 结果应该等于6 */然而,预处理程序把宏展开:int a = ( (5) = 0) ? (5) : -(5) + 1;“+”运算符的优先级比“?”要高

45、,所以上面的式子其实是:int a = ( (5) = 0) ? (5) : (-(5) + 1);/* a = 5 !*/为了避免这样的漏洞,我们要小心翼翼地提方,尽可能采用适当的措施:#define abs(x) ( ( (x) = 0) ? (x) : -(x)虽然这里“加括号”可以解决问题,但由于宏有不少“副作用”,某些场合就颇为棘手。因为宏仅仅是一种记号替换,不像函数,它没有办法知道真正的参数时什么,从而无法对参数进行检查,也不能像函数那样把某些运算局限在内部。因此由C+提出和实现了“内联涵数”,它本身的确是函数,但必要时编译器可以把它的代码像宏那样“嵌入”到调用它的地方,从而既节省系统开销又没有宏的缺点。今天,C99也拥有了这项语言特性2。4.2程序设计中的异常处理我曾经考虑过学习C+中的try catch throw 异常处理机制,然后用在SVM虚拟机的实现中。但最终未采用该机制,SVM虚拟机的执行效率已经很难让人恭维了,加入该机制只会使虚拟机的运行更慢。不过在此,仍简要介绍一下该机制。在异常处理技术得到广泛应用之前,即使应用程序理出现了奇怪的事情,你也只能依靠全局变量和函数的返回值来判断到底发生了什么事情。然而,你也不能期望一个孤零零的出错值总是能向你提供足够的信息,函数出错并不可怕,可要是函数反回了一个“

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 学术论文 > 毕业论文/毕业设计

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        获赠5币

©2010-2024 宁波自信网络信息技术有限公司  版权所有

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服