PA2.2&2.3

时间:2021-08-05
本文章向大家介绍PA2.2&2.3,主要包括PA2.2&2.3使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

目录

思考题

1.什么是 API

API(Application Programming Interface)是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而又无需访问原码,或理解内部工作机制的细节。

2.AM 属于硬件还是软件?

AM属于软件,是对底层的抽象。

AM 和操作系统一样。AM是一个抽象计算机模型,通过一组API实现对计算机底层细节的抽象,为程序运行提供最基本的软件支持,是最贴近硬件的软件。操作系统是位于硬件与软件之间,而AM也是位于NEMU(硬件)与软件之间,他们的功能都是通过API实现对硬件的抽象。

3.堆和栈在哪里?

  • 在内存里

4.回忆运行过程

首先默认编译到x86-nemu 中,由ALL=dummy 可知make run 指令调用了nexus-am/am/arch/x86-nemu/img/run 启动nemu 来运行dummy.c

5.神奇的eflags

+-----+-----+------------------------------------+
|  SF |  OF |               实例                  |
+-----+-----+------------------------------------+
|  0  |  0  |               2 - 1                |
+-----+-----+------------------------------------+
|  0  |  1  |         0xf0000000-0x00000001      |
+-----+-----+------------------------------------+
|  1  |  0  |         0x80000001-0x00000001      |
+-----+-----+------------------------------------+
|  1  |  1  |         0x0f000000-0x00000001      |
+-----+-----+------------------------------------+

6.这是巧合吗?

ja

无符号整数op1>op2

CF=0 AND ZF=0

jb

无符号整数op1<op2

CF=1 AND ZF=0

jg

带符号整数op1>op2

SF=OF AND ZF=0

jl

带符号整数op1<op2

SF≠OF

7.nemu的本质

lable1:
	x = x - 1
	a = a + 1
	jne x, lable1
	
lable2:
	y = y - 1
	a = a + 1
	jne y, lable2

还需要输入和输出功能,还需要通过图形界面进行交互

8.设备是如何工作的?

IO接口是连接CPU与外部设备的逻辑控制部件,其功能是协调CPU和外设之间的工作。CPU通过接口发送指令给设备,设备接受指令并执行后把结果通过接口传回CPU。

9. CPU 需要知道设备是如何工作的吗?

不需要,cpu的作用主要是传递指令等待机器运行返回实验结果不需要知道进行了什么工作。

10. 什么是驱动?

驱动,是指驱动计算机里软件的程序。驱动程序全称设备驱动程序,是添加到操作系统中的特殊程序,其中包含有关硬件设备的信息。此信息能够使计算机与相应的设备进行通信。驱动程序是硬件厂商根据操作系统编写的配置文件,可以说没有驱动程序,计算机中的硬件就无法工作。

驱动是操作系统与硬件之间的桥梁,操作系统有了驱动,才能调度硬件。一般应用程序在操作系统之上,利用操作系统提供的API完成相应的任务。

11. cpu知道吗?

不需要,只需要把特定地址上的数值设定为指定的值即可。

12.再次理解volatile

O2优化下编译

gcc -O2 -o fun fun.c
查看反汇编

objdump -s -d fun > fun.txt
添加volatile关键字的反汇编

不添加volatile关键字的反汇编

若不加volatile,则从反汇编中可看出少了很多指令,第11a7行会陷入死循环。

13.hello world运行在哪里?

不一样,此helloworld 程序运行在AM 中,程序设计课上的运行在硬件层面

14.如何检测很多个键同时被按下?

当按下一个键的时候, 键盘将会发送该键的通码; 当释放一个键的时候, 键盘将会发送该键的断码。每当用户敲下/释放按键时, 将会把相应的键盘码放入数据寄存器, 同时把状态寄存器的标志设置为 1, 表示有按键事件发生. CPU 可以通过端口 I/O 访问这些寄存器, 获得键盘码。每个按键的通码断码都不同,所以可以识别出不同的按键。

15.编译与链接Ⅰ

  • 去掉static

    没遇报错

  • 去掉inline

    该函数仅用static修饰,则为静态函数,只能被该函数所在文件引用,然而该文件并没用其他函数使用该函数,因此导致defined but not used

  • 去掉staticinline

    当多个文件包含同一个头文件时,而头文件中没有加上条件编译,就会独立的解释,然后生成每个文件生成独立的标示符。在编译器连接时,就会将工程中所有的符号整合在一起,由于,文件中有重名变量,于是就出现了重复定义的错误。

16.编译与链接Ⅱ(10分)

  1. 29个

    此时dummy是静态局部变量,可以看到有29个文件重新编译,则有29个变量实体。

  2. 58

    由于没初始化,两次定义的符号都是弱符号,编译器允许弱符号多次定义且编译器会把这两次当作两个不同的符号对待。重新编译后,仍然是那29个文件重新编译,则又多了29个该变量实体,则一共58个。

  3. 初始化

    问题:变量重定义

    原因:变量赋初值后则成为强符号,编译器不允许强符号多次定义,则报错。

17.I/O 端口与接口(10分)

  1. 地址范围:

    1K=2^10,端口范围0000H~0400H

    16根地址总线,寻址范围也就是216,因为1K=210,所以寻址范围为216/210=64K,地址范围0000H~FFFFH

  2. I/O三种控制方式:程序直接控制、终端控制、DMA控制。

    课本中由有这样的例子:

    首先DMA控制器初始化,然后发送“启动DMA传送”命令以启动外设进行I/O操作,发送完“启动DMA传送”命令后, CPU转去执行其他进程,而请求I/O的用户进程被阻塞。在CPU执行其他进程的过程中,DMA控制器外设和主存进行数据交换。DMA控制器每完成一个数据的传送,就将字计数器减1,并修改主存地址,当字计数器为0时,完成所有I/O操作,此时,DMA控制器将向CPU发送“DMA完成”中断请求,CPU检测到后调出相应的中断服务程序执行。CPU在中断服务程序中,解除用户进程的阻塞状态而使用户进程进入就绪序列,然后中断返回,再回到被打断的进程继续执行。

    常见于硬盘。

18. git log截图

实验题

1.实现剩余所有 x86 指令

由于在PA2.1中补全了绝大多数的指令所以导致在PA2.2 中测试时大部分的测试样例全都通过了

下面为补全指令之后全部的测试结果图

  • add-longlong 实现在nemu/src/cpu/exec/cc.c 中的TODO 内容填写switch语句
  • add
  • bit
  • bubble-sort
  • dummy
  • fact
  • fib
  • goldbach
  • if-else
  • leap-year
  • load-store
  • matrix-mul
  • max
  • min3
  • mov-c
  • movsx
  • mul-longlong
  • pascal
  • prime
  • quick-sort
  • recursion
  • select-sort
  • shift
  • shuixianhua
  • sub-longlong
  • sum
  • switch
  • to-lower-case
  • unalign
  • wanshu
  • string
  • hello-str

2.通过⼀键回归测试

nemu 目录下输入bash runall.sh 进行一键测试结果如下

3.IN/OUT 指令

首先打开 nemu/include/common.h中的宏定义HAS_IOE

填写opcode_table

 /* 0xe4 */	IDEXW(in_I2a, in, 1), IDEX(in_I2a, in), IDEXW(out_a2I, out, 1), IDEX(out_a2I, out),
 /* 0xec */ IDEXW(in_dx2a, in, 1), IDEX(in_dx2a, in), IDEXW(out_a2dx, out, 1), IDEX(out_a2dx, out),

之后在all-instr中声明make_EHlper

 make_EHelper(in);
make_EHelper(out);

补全函数在system.c

make_EHelper(in) {
  //TODO();
	t1 = pio_read(id_src->val, id_dest->width);//调用pio_read
	operand_write(id_dest, &t1);//写入
  	print_asm_template2(in);

#ifdef DIFF_TEST
  diff_test_skip_qemu();
#endif
}

make_EHelper(out) {
  //TODO();
	pio_write(id_dest->val, id_dest->width, id_src->val);//调用pio_write,直接写入
  	print_asm_template2(out);

#ifdef DIFF_TEST
  diff_test_skip_qemu();
#endif
}

之后在nexus-am/am/arch/x86-nemu/src/trm.c定义宏HAS_SERIAL

之后运行helloworld 实现运行

同时配置好X11 之后成功弹出了窗口

实现成功。

4.实现时钟设备

实现_uptime 函数ioe.c

之后进行测试实现更新时间

5.运行跑分项目

首先注释掉DEBUGDIFF-TEST之后进入内部跑分

  • dhrystone
  • coremark
  • microbench

6.实现键盘设备

实现_read_key 函数在ioe.c

运行之后出现NEMU 界面,之后在界面中输入键盘键入信息即可

7.添加内存映射 I/O

nemu/src/memory/mrmory.c 中填写paddr_readpaddr_write 函数测试如下

8.运行打字小游戏

实现打字小游戏

遇到的问题及解决方法

  1. 遇到的问题:在实现键盘设备keytest 时虽然实现了_read_key 函数并且无错误到那时还是在运行时显示不出读取的键盘信息

    解决方案:经过查找问题发现,运行需要触发图形界面需要连接到Xming打开之后需要设置PUTTY中的X11 连接之后在运行就可以成功实现了

心得感悟

本次实验难度不太大,有了PA2.1实验的基础之后添加令变得有思路起来,之后实现的各种冯诺依曼据计算机的基础功能也是依赖于前面学到的一部分的知识,同时指令实现优势对之前的学过的指令的复习过程,最后实现打字小游戏还是有成就感的,这次的实验可以更加了解到计算机的各种功能,较为深入但是i理解起来并不繁琐。

备注

明天会更好,助教真帅

原文地址:https://www.cnblogs.com/shangjin2001/p/15102149.html