CS:APP2e Y86处理器模拟器∗指南

Randal E.Bryant

David R. O’Hallaron

2013年7月29日

  本文档描述了处理器模拟器,伴随的表示在第4章Y86处理器架构的计算机系统:一个程序员的角度来看,第二版。这些模拟器模型的三种不同的处理器设计:SEQ,SEQ +和PIPE。

  1. 安装

  模拟器的代码通常是分布于一个名叫sim.tar的文件之中,tar格式文件。你可以从CS:APP2e Web site (csapp.cs.cmu.edu)这个网站获取一份拷贝的文件。在tar文件的目录中安装代码,执行以下步骤:

  1. unix> tar xf sim.tar
  2. unix> cd
  3. sim unix> make clean
  4. unix> make

  默认情况下,这个生成GUI(图形用户界面graphic user interface)版本的模拟器要求你有在系统中安装Tcl/Tk。若你没安装,那么你可以选择安装TTY-only版本,TTY-only的标准输出是ASCII文本。参见README文件如何生成GUI和TTY版本。

  Sim目录包含以下子目录:

  Misc:源代码文件中的实用工具,例如:YAS(Y86j集合),YIS(Y86指令集模拟器)和HCL2C(HCL翻译到C)。它还包括isa,c源文件所使用的所有处理器模拟器。

  Seq:SEQ和SEQ+模拟器的源代码。4.49和4.50包含HCL文件作业问题。参见README对不同版本的模拟器编译的说明。

  Pipe:pipe模拟器的源代码。4.52-4.57包括HCL文件问题。参见README对不同版本的模拟器编译的说明。

  Y86-code:Y86汇编代码的那一张中所示的实例程序。你可以在这些基础程序上测试你修改的模拟器。参见README文件对如何运行这些测试进行说明。作为一个运行的实例,我们将使用在这个子目录中的asum.ys。这个程序在CS:APP2e的图4.8中说明。编译后的版本如图一所示。

  Ptest:生成在不同的指令,不同的可能性和不同的风险下系统回归测试的脚本。这些脚本能够很好的帮助你在你的工程中发现bug。

  1. 1 | # Execution begins at address 0
  2. 2 0x000: | .pos 0
  3. 3 0x000: 30f400010000 | init: irmovl Stack, %esp # Set up stack pointer
  4. 4 0x006: 30f500010000 | irmovl Stack, %ebp # Set up base pointer
  5. 5 0x00c: 8024000000 | call Main # Execute main program
  6. 6 0x011: 00 | halt # Terminate program
  7. 7 |
  8. 8 | # Array of 4 elements
  9. 9 0x014: | .align 4
  10. 10 0x014: 0d000000 | array: .long 0xd
  11. 11 0x018: c0000000 | .long 0xc0
  12. 12 0x01c: 000b0000 | .long 0xb00
  13. 13 0x020: 00a00000 | .long 0xa000
  14. 14 |
  15. 15 0x024: a05f | Main: pushl %ebp
  16. 16 0x026: 2045 | rrmovl %esp,%ebp
  17. 17 0x028: 30f004000000 | irmovl $4,%eax
  18. 18 0x02e: a00f | pushl %eax # Push 4
  19. 19 0x030: 30f214000000 | irmovl array,%edx
  20. 20 0x036: a02f | pushl %edx # Push array
  21. 21 0x038: 8042000000 | call Sum # Sum(array, 4)
  22. 22 0x03d: 2054 | rrmovl %ebp,%esp
  23. 23 0x03f: b05f | popl %ebp
  24. 24 0x041: 90 | ret
  25. 25 |
  26. 26 | # int Sum(int *Start, int Count)
  27. 27 0x042: a05f | Sum: pushl %ebp
  28. 28 0x044: 2045 | rrmovl %esp,%ebp
  29. 29 0x046: 501508000000 | mrmovl 8(%ebp),%ecx # ecx = Start
  30. 30 0x04c: 50250c000000 | mrmovl 12(%ebp),%edx # edx = Count
  31. 31 0x052: 6300 | xorl %eax,%eax # sum = 0
  32. 32 0x054: 6222 | andl %edx,%edx # Set condition codes
  33. 33 0x056: 7378000000 | je End
  34. 34 0x05b: 506100000000 | Loop: mrmovl (%ecx),%esi # get *Start
  35. 35 0x061: 6060 | addl %esi,%eax # add to sum
  36. 36 0x063: 30f304000000 | irmovl $4,%ebx #
  37. 37 0x069: 6031 | addl %ebx,%ecx # Start++
  38. 38 0x06b: 30f3ffffffff | irmovl $-1,%ebx #
  39. 39 0x071: 6032 | addl %ebx,%edx # Count-
  40. 40 0x073: 745b000000 | jne Loop # Stop when 0
  41. 41 0x078: 2054 | End: rrmovl %ebp,%esp
  42. 42 0x07a: b05f | popl %ebp
  43. 43 0x07c: 90 | ret
  44. 44 |
  45. 45 | # The stack starts here and grows to lower addresses
  46. 46 0x100: | .pos 0x100
  47. 47 0x100: | Stack:

图1:代码实例。这段代码在y86-code子目录中的asum.yo文件中。

  2、 实用程序

  安装完成后,misc目录中包含两种有用的代码。

  YAS:Y86汇编程序。这需要一个有.ys扩展名的Y86文件,用.yo文件生成一个.ys文件。生成的文件包括一个ASCII版本的代码,像图一所示(相同的程序所示在CS:APP2e的图4.8中)最简单的方法来调用一个汇编程序,可以以使用或者建立一个汇编到y-86 code这个子目录文件中。例如,想要汇编这个目录中的asum.ys文件,我们可以使用这样的命令:

  1. unix> make asum.yo

  YIS:Y86指令模拟器。这个程序在Y86机器级执行指令根据指令集定义。例如,假设你想运行在y86代码目录下的程序asum.yo。简单的运行:

  1. unix> ../misc/yis asum.yo

  YIS模拟执行程序然后打印所有改变的寄存器或者是主存在终端上。就像CS:APP2e 4.1节所述。

  3、处理器模拟器

  对于SEQ,SEQ+和PIPE三个处理器,我们分别提供了SSIM,SSIM+和PSIM。每一个模拟器可以在TTY和GUI模式下运行。

  TTY模式 使用一个简单的,面对终端的接口。打印所有在终端输出上。虽然调试不是很方便,但可以安装在任何系统,可用于自动化测试。默认对所有模拟器。

  GUI模式 有一个图形界面,不久将被描述,对于观察处理机活动和调试修改版本很有用。然而,它需要在你的系统上安装Tcl/Tk。使用-g调用命令行选项。

  3.1 命令行选项

  你可以从命令行使用下列选项:

  1. -h 打印所有命令行选项的摘要
  2. -g GUI模式下运行模拟器(默认TTY模式)
  3. -t 运行处理器和ISA模拟器,比较内存的结果的值,寄存器文件和条件代码。如果没有发现差异,就打印“ISA检查成功”。否则,打印关于寄存器文件或者内存不同的信息。这个功能对于测试处理器设计非常有用。
  4. -l m设置指令限制,在停止之前最多执行m条指令(默认10000指令)
  5. -v n信息显示级别设置为n,这个值默认是2,在0-2之间。

  模拟器中在GUI模式上运行必须调用一个文件对象的名称在命令行上。在TTY模式下文件的名称是可选的,默认情况下来自stdin。

  下面是一些调用模拟器的典型(从y86-code子目录):

  1. unix> ../seq/ssim -h
  2. unix> ../seq/ssim -t < asum.yo
  3. unix> ../pipe/psim -t -g asum.yo

  第一种情况打印了SSIM在命令行选项的摘要。第二种选项在TTY下运行SEQ模拟器,从stdin中读取目标文件asum.yo。第三种情况在GUI模式下运行PIPE模拟器,执行指令对象文件asum.yo。在第二中和第三种情况之中,将结果与更高级ISA模拟器的结果相对比。

  3.2 SEQ和SEQ+模拟器

  SEQ处理器的GUI版本在命令行中被对象文件名调用:

  1. unix> ../seq/ssim -g asum.yo &

  在最后有“&”的命令允许模拟器在后台模式运行。启动模拟器程序并创建三个窗口,如图2-4.

第一个窗口(图二)是主要的控制面板。如果HCL被HCL2C用-n 选项编译了,主控制面板的标题将显示“Y86处理器:名称”。否则只显示“Y86处理器”

  主控制窗口包含处理器控制按钮以及处理器的信息处理状态。窗口不同的部分在途中有所标记:

  控制:位于顶部的按钮控制模拟器。点击退出按钮退出模拟器。单机Go按钮可以使模拟器开始运行。单机停止按钮使模拟器暂时停止。单机步骤按钮可以使模拟器执行一条指令然后停止。单机重置按钮使模拟器回到初始状态,程序计数器的地址0,寄存器设置变为0,内存除了程序清零,设定条件规范ZF=1,CF=0,OF=0。程序状态设定为AOK。

图二:SEQ模拟器主控制面板

图三:SEQ模拟器代码显示窗口

图四:SEQ模拟器内存显示窗口

  当模拟器运行时,按钮下面的滑块可以控制模拟器的速度。向右移动可以使模拟器运行速度更快。

  阶段信号:这一部分显示不同处理器信号在当前的指令求值期间的值。这些信号几乎是相同的,如CSAPP2e中的图4.23所示。主要的区别在于模拟器显示在Instr中指令的名称,而不是icode和ifun的数值。同样所有寄存器标识符显示他们的名字,而不是他们的数值,用”----”表示不需要注册访问。

  寄存器文件:这部分显示了8个程序寄存器的值。已经更新的了最新的寄存器会浅蓝色显示。寄存器的内容不会显示,指导第一次设置为非零的值。 注意当一条指令写入程序寄存器时,指到下一个时钟周期的开始,寄存器文件不会更新。这意味着你必须一步一步的看到寄存器更新。

  状态:显示当前正在执行指令的状态。这些值可能是:

  1. AOK:没有问题
  2. ADR:寻址错误,试图读取一个指令或者试图去读写一个数据。地址不能超过0X0fff
  3. INS:遇到非法指令。
  4. HLT:遇到停止指令。

  状态代码:显示三个状态标志:ZF,SF和OF。

  注意:当一个指令改编状态代码,直到下一个时钟周期开始,状态代码寄存器不更新。这意味着你要一步一步看到更新。

  处理器asum第38行第二线程执行状态如图2所示。程序yo如图一所示,我们可以看见程序计数器在0X06b,它处理指令将%ebx,%ecx相加,寄存器%eax存储0xcd,前两个数组的和。%edx保存3,计数递减。寄存器%ecx保存0x1c,第三个数组的地址。寄存器%ebx存储4(从第36行)但有一个0xFFFFFFFF写入这个寄存器(由于dstE存放在%ebx中,数值是0xFFFFFFFF)。写入将在下个始终周期开始。

  窗口(图三所示)描述了目标代码已经被模拟器执行了。编辑框标识被执行的程序的文件名。你可以编辑文件名在这个窗口,点击登陆按钮登陆新的程序。左边显示已经被执行的对象代码,右边显示了汇编代码的文本文件。中心有一个星号表示指令目前正在被模拟。这相对应于图一所示asum.yo的第38行。

  图四所示关于内存的内容。它只显示当程序开始执行时最大值和最小值地址的位置。每一行显示内存的数据。因此每一行显示内存16字节的内存,这些字节地址只有最低有效位16字节。左边的内容是根地址,最低有效位的位置显示”-”。每一列之后对应最低地址位数0x0,0x4,0x8,0xc。图四所示的例子中有箭头表明存储器地址0x00e8,0x00e4,0x00e8,0x00ec。

  图中描述了关于求和程序在运行时,asum.yo程序在存储器中堆栈的内容。我们可以看到到目前为止堆栈的运行情况,我们能够看到%esp和%ebp被初始化为0x100(3行和4行所示)。在第五行推出调用返回指针0x011,被写入地址0x00fc。程序通过推出%ebp开始,将0x100写入0x00f8。然后退出%eax的值(18行),将0x4写入0x00f4和%edx(20行)。将0x14(数组)写入0x00f0。在第21行调用Sum导致返回指针0x3d被写入地址0x00ec。在运行sum时,存储器先推出%ebp的值导致0xf8被写入地址0x00e8。这归因于将数值在存储器和堆栈指针被设定为0xe8.

  图5显示了在执行相同代码文件和有相同点的程序的SEQ+模拟器的控制面板窗口。我们可以看出唯一不同的就是排序不同的流程和不同的信号列表。这些信号在CSAPP2e图4.40中有对应。SEQ+模拟器还声称代码和存储器窗口。在SEQ模拟器中他们的格式相同。

  3.3 PIPE模拟器

  PIPE模拟器也生成三种窗口。图6显示了控制面板。它的控制有相同的设定,寄存器文件和条件代码有相同的显示。中间的部分显示了寄存器的状态。不同的字段在CSAPP2e的图4.52中有相应的对应。在面板的底部显示数据的周期模拟(不包括最初的周期),完成数据的指令,结果CPI。

  见图7的观察图,每个pipeline寄存器显示了两个部分。上面白色框中的数值显示了最近pipeline寄存器中的数值。较低的灰色背景中的数值显示了pipeline中的输出。除非寄存器。。。。。。,这些在下一个时钟周期被寄存器载入。

  通过PIPE模拟器的流量和在SEQ和SEQ+模拟器中的不一样。在SEQ和SEQ+中,控制面板显示执行单一命令的数值结果。每一步执行模拟器处理一条指令。在PIPE中,控制面板显示多种通过pipeline的命令流。每一步执行模拟器执行这一阶段每一条命令的数值计算。

  图八显示了PIPE模拟器的代码显示。格式类似于SEQ和SEQ+,除了执行命令时单一的标记指示,用字符F、D、E、M和W来显示pipeline每一阶段的取回、解码、执行、内存、重写阶段。

图5:SEQ+模拟器的主控制界面

图6:PIPE模拟器的主控制界面

图7:PIPE模拟器主控板查看单一PIPE寄存器

图8:PIPE模拟器代码显示窗口

  PIPE模拟器同样生成一个窗口来显示存储目录,SEQ模拟器有相同的格式。(图4)

  图6和图8的例子显示了当执行图1,34-40行的循环时显示pipeline的状态。我们可以看见模拟器开始第二轮迭代,每个阶段的状态如下:

  1. 重写:loop-closing指令(40行)完成。
  2. 存储:mrmov指令(24行)从地址0x018读出。我们可以看见在pipeline寄存器MvalE的地址,和pipeline寄存器W中作为valM的输入,从存储器中读取的数值。
  3. 执行:这一阶段包含一个气泡。这个气泡的产生是由于mrmovl命令(34行)和addl命令(35行)之间的以来关系。这个泡沫就像是nop指令。它解释了为什么没有指令在图8中标记”E”。
  4. 解码:addl指令(第35行)刚刚从寄存器%eax读取0x00D。也从寄存器%esi读到数据0x00D。但是我们可以看到转发逻辑并没有使用刚刚从内存(在pipeline寄存器W中视为对valM的输入)中读取到的数据0x0C0作为valA的新值(在pipeline寄存器E中视为对valA的输入)
  5. 读取:irmovl指令(38行)刚从地址0x063获取到,电脑的新值预计是0x069

  每个阶段用他们的状态字段统计联系起来。这一字段显示了指令在pipeline中那一阶段的状态。AOK状态意味着没有遇到任何异常。状态BUB表明了在次阶段中有一个泡沫 ,并不是一个标准的指令。另一种一些可能的状态是:ADR:当一个无效的内存地址被引用时;INS:遇到一个不合法的指令代码;PIP:当在pipeline中遇到问题时(这常常发生在停止和某些被设置为1的pipeline寄存器出现泡沫信号);HTL:与带了一个停止命令。当遇到上述的四种情况,模拟器会停止。

  一些建议:

  以下是一些其它的技巧,我们从学习使用这些模拟器的经验。

  熟悉这些模拟器的操作。尝试去运行一些在y86-code目录中的示例代码。确保你理解每条指令是如何处理一些小的例子。看一些有趣的情况,例如:如在驱动的装置,程序的返回值。

  你需要寻找信息。看到数据转发的影响时尤其棘手。有七个可能的源信号valA流水线寄存器E,和六个可能的源信号valB。选择哪一个,你需要比较这些流水线寄存器输入字段值的可能来源。可能的来源有:

  1. R[d srcA] 源寄存器被输入在流水线寄存器srcA E中。寄存器内容显示在底部。
  2. R(d srcB) 源寄存器被输入在流水线寄存器srcB E中。寄存器内容显示在底部。
  3. D valP 这个值是流水线寄存器状态的一部分。
  4. e valE 这个值是valE的输入字段在流水线寄存器M中。
  5. M valE 这个值是M流水线寄存器的状态的一部分。
  6. m valM 这个值是valE的输入字段在流水线寄存器W中。
  7. W valE 这个值是W流水线寄存器的状态的一部分。
  8. W valM 这个值是M流水线寄存器的状态的一部分。

  你不要写重复的代码。由于数据和代码共享相同的地址空间,很容易有一个项目覆盖一些代码,在它试图再次执行指令时导致完全混乱,。重要的是设置距代码足够远的堆栈来避免这种情况。

  避免大的地址值。模拟器不允许任何大于 0x0FFF的地址。此外,如果你修改内存位置时地址较大内存显示会慢。

  注意一些GUI模式模拟器的“特性”(SSIM SSIM +,PSIM)

  • 你必须从他们的主目录执行程序。换句话说,去运行SSIM或SSIM+,你一定要处于seq目录中,然而你运行PSIM子目录必须在管道中。这个需求出现是由于Tcl解释器定位模拟器配置文件的方式。
  • 如果你是在Unix机器上运行GUI模式,记得要初始化显示环境变量:

    1. unix> setenv DISPLAY myhost.edu:0
  • 在一些Unix X窗口管理器中,把“程序代码”窗口开始运行作为一个封闭的图标。如果您没有看到这个窗口当模拟器启动时,你需要手动点击来扩大它。

  • 一些微软的windows X服务器,当存储内容更改时存储内容的窗口不会自动调整自己的大小,在这种情况下,你需要自己去手动调整来查看内存的值
  • 如果你要求他们执行一个不是有限的Y86文件,模拟器将因错误而终止。

CS:APP2e Y86处理器模拟器∗指南的更多相关文章

  1. ubuntu12.04 安装CS:APP Y86模拟器

    下的第一UBUNTU12.04下Y86模拟器的安装:(參考http://archive.cnblogs.com/a/1865627/ 作适当改动) 1.安装bison和flex词法分析工具 sudo ...

  2. CS:APP3e 深入理解计算机系统_3e Y86-64模拟器指南

    详细的题目要求和资源可以到 http://csapp.cs.cmu.edu/3e/labs.html 或者 http://www.cs.cmu.edu/~./213/schedule.html 获取. ...

  3. CS基础课不完全自学指南

    本文讲的是计算机学生怎么自学专业课,说长点就是该如何借助网络上已有的高质量学习资源(主要是公开课)来系统性的来点亮自己的CS技能树.这篇文章完全就是一篇自学性质的指南,需要对编程充满热情,起码觉得编程 ...

  4. Y86处理器的各个阶段

    0x00e:30f480000000        |              irmovl $128,%esp  实现所有Y86指令所需要的计算分为6个基本阶段:取值.译码.执行.访存.写回和更新 ...

  5. 深入理解计算机系统_3e 第四章家庭作业(部分) CS:APP3e chapter 4 homework

    4.52以后的题目中的代码大多是书上的,如需使用请联系 randy.bryant@cs.cmu.edu 更新:关于编译Y86-64中遇到的问题,可以参考一下CS:APP3e 深入理解计算机系统_3e ...

  6. 深入理解计算机系统(4.1)------Y86指令集体系结构

    本章我们将进入处理器体系结构介绍的神秘海洋中,我们熟悉的手机,电脑等设备的核心硬件都离不开处理器.处理器可以称的上是人类创造的最复杂的系统之一,一块手指大小的硅片,可以容纳一个完整的高性能处理器.大的 ...

  7. Hello, Android 快速入门

    Hello, Android Android 开发与 Xamarin 简介 在这两节指南中,我们将 (使用 Xamarin Studio或 Visual Studio)建立我们的第一个 Xamarin ...

  8. 【海思】Hi3531A SPI功能的详细配置以及使用

    目录 一.前言 二.SPI管脚信息获取 2.1 SPI_SCLK.SPI_SDI.SPI_SDO管脚复用寄存器 2.2 片选SPI_CSN0-SPI_CSN3管脚寄存器 三.配置和使能与SPI相关的管 ...

  9. armv7 armv7s arm64

    arm处理器以其低功耗和小尺寸而闻名,几乎所有的手机处理器都是基于arm,在嵌入式系统中应用非常广泛.   armv6, armv7, armv7s, arm64指的是arm处理器的指令集. i386 ...

随机推荐

  1. nim2 取石头youxi

    a先把石头分堆,然后bababa的顺序取石头,只能取其中一堆中的若干颗(不能不取) 这种问题先考虑 先取者的胜态问题 (1,1)先取者必败, 所以(1,x),当x>1时可以转换为(1,1)使后取 ...

  2. Effective Java 56 Adhere to generally accepted naming conventions

    Typographical naming conventions Identifier Type Type Examples Package com.google.inject, org.joda.t ...

  3. 数据库相关 sql 语句

    1.操作某数据库 use 数据库名称,然后可以操作该数据库下的某张表 2.$res=mysql_query($sql); 该语句如果用在封装的函数体里,则不用传入第二个参数$conn来指定连接,这样才 ...

  4. hdu 2089 不要62--数位dp入门

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Des ...

  5. hdu 1506

    题目中叫求一个最大的区域,则第i个矩形对应的面积是ave[i] = (r[i] – l[i] + 1) * a[i];l[i]表示以它这个高度所能到达的最左边的位置(最左一个高度不小于它的高度的位置) ...

  6. HTTP详解2-请求、响应、缓存

    1. HTTP请求格式 做过Socket编程的人都知道,当我们设计一个通信协议时,“消息头/消息体”的分割方式是很常用的,消息头告诉对方这个消息是干什么的,消息体告诉对方怎么干.HTTP协议传输的消息 ...

  7. 《互联网+:从IT到DT》:阿里公关稿,数据与案例不够全面客观,电商部分有一些生动的例子,三星

    本书是阿里研究院的集体创作,当然要从阿里的视角写,因此其他的互联网巨头的信息很少涉及,对阿里不利的案例很少涉及. 关于“互联网+”,关于“互联网+”跟互联网的区别,书的开头有一点介绍.我感觉总体来说直 ...

  8. 【温故而知新-Javascript】为DOM元素设置样式

    1. 使用样式表 可以通过document.styleSheets属性访问文档中可用的CSS样式表,它会返回一组对象集合,这些对象代表了与文档管理的各个样式表. 每个样式表 都由一个CSSStyleS ...

  9. 边工作边刷题:70天一遍leetcode: day 85-1

    Inorder Successor in BST 要点:这题要注意的是如果不是BST,没法从树结构上从root向那边找p,只能遍历.而根据BST,可以只走正确方向 如果不检查right子树,可以从ro ...

  10. python中list注意事项

    今天写python出了一个小插曲,具体情况见代码: >>> a = [1,2,3] >>> import queue >>> q = queue. ...