2021-2022-1学期 20212417《网络空间安全专业导论》第三周学习总结
目录
第六章 低级程序设计语言与伪代码
6.1 计算机操作
(1) 计算机时能够存储、检索和处理数据的可编程电子设备。
(2) 操作数据的指令与数据一起存储在机器中。要改变计算机对数据的处理,只需要改变指令即可。
(3) 存储、检索和处理是计算机能够对数据执行的动作。在机器层,处理涉及在数据值上执行算术和逻辑操作。
6.2 机器语言
(1) 机器语言——由计算机直接使用的二进制编码指令构成的语言。
(2) 每种处理器都有自己专用的机器指令集合,这些指令是处理器唯一真正能够执行的指令。由于指令的数量有限,所以处理器的设计者就列出所有的指令,给每个指令分配一个二进制代码来表示它们。
和汉字一样,指令不能随便创造。
(3) 每条机器语言指令只能执行一个非常低级的任务。在机器语言中,处理过程中每一个微小的步骤都必须被明确地编码。
但大多数程序都是用高级程序编写的,然后翻译成机器语言。这种体验会强化计算机的基本定义。
-
Pep/8:一台虚拟机
(1) 每种类型的CPU都有它能理解的自己的机器语言。
(2) 虚拟机——为了模拟真实机器的重要特征而设计的假象机器。
Pep/8是由斯坦利·沃福德设计的虚拟计算机。 -
Pep/8反应的重要特征
(1) Pep/8的内存单元由65536字节的存储空间构成。
(2) Pep/8的三个重点研究的寄存器:- 程序计数器(PC):其中包含下一条即将被执行的指令的地址。
- 指令寄存器(IR):其中包含正在被执行的指令的一个副本。
- 累加器:也是一个寄存器。
(3) 可用的比特数决定了我们可以使用的内存大小。
- 指令格式
(1)指令要先进入指令寄存器,然后经过译解,最后被执行。
(2)一条指令由两部分组成:8位的指令说明符和(可选的)16位的操作数说明符。 - 指令说明符(指令的第一个字节)说明了要执行什么操作和如何解释操作数的位置。
- 操作数说明符(指令的第二、三个字节)存放的是操作数本身或者操作数的地址。
(3)有些指令没有操作数说明符。
(4)3比特的寻址模式说明符表示了怎样解析指令中的操作数部分。 - 寻址模式是000——操作数说明符存储操作数——称为立即寻址(i)。
- 寻址模式是001——操作数说明符中存储操作数所在的内存地址名称——称为直接寻
址(d)。
……
立即选址和直接选址两个模式之间的差别很重要,因为它决定了操作中设计的数据存
储或将要被存储的位置。
(5)没有操作数(要处理的数据)的指令称为一元指令,这些指令没有操作数说明符。
即一元指令的长度仅为一个字节。
- 一些示例指令
(1)0000——停止执行
(2)1100——将操作数载入寄存器A(累加器)中
(3)1110——将寄存器A的内容存储到操作数中
(4)0111——将操作数加到寄存器A中
(5)1000——减去操作数
(6)01001——把字符输入操作数
(7)01010——从操作数输出字符
6.3 一个程序实例
(1)在屏幕上显示“Hello”需要用到6条指令:5条用于显示字符,1条用于指示过程的结束。
(2)编程语言中常用的模式:用双引号指一组字符,用单引号指单个字符。
6.3.1 手工模拟
通过执行读取-执行周期的步骤模拟这个程序的执行。
6.3.2 Pep/8 模拟程序
(1)要运行一个程序,需要逐字节的输入十六位进制的代码,每个字节之间用空格隔开,以zz结束程序。模拟程序可以识别程序结尾处的两个z。
(2)单击Pep/8图标来启动程序。屏幕中可能显示多种情况中的一种,但是每一种都包含一个标有“Object Code(结果代码)”的部分。
(3)装入程序——软件用于读取机器语言并把它载入内存的部分。
*过程中要保证终端I/O按钮是选中的。
(4)Pep/8可以让你查看CPU在执行每条指令的时候都发生了什么。
6.4 汇编语言
(1)汇编语言——一种低级语言,用助记码表示特定计算机的机器语言指令。
(2)汇编器——把汇编语言程序翻译成机器代码的程序。
6.4.1 Pep/8汇编语言
本小节罗列出了一些常用的助记忆码。
6.4.2 汇编器指令
汇编器指令:翻译程序使用的指令,也叫伪操作。
6.4.3 Hello程序的汇编语言版本
(1)Pep/8汇编语言允许我们直接指定字符输出,还允许我们在指令旁边添加注释。
(2)注释:为程序读者提供的解释性文字。无论编写什么程序,注释都是一个重要组成部分。
(3)汇编器窗口中显示了指令被指定的地址、结果代码和汇编语言代码。
(4)运行一个汇编语言的过程:
汇编语言程序→输入→汇编器→输出→机器代码程序
6.4.4 一个新程序
我们可以根据算法对程序建模。
本节具体对编写加总程序进行讲解。
6.4.5 具有分支的程序
一个将程序计数器设为下一条被执行的指令地址的BR指令可以改变程序计数器。
本节具体对分支代码的操作进行讲解。
6.4.6 具有循环的程序
我们可以创建技术循环代码,这部分代码可以重复指定次数。在代码循环中一个值被读取并累加。
本节具体对循环代码的操作进行讲解。
6.5 表达算法
(1)算法:解决方案的计划或概要,或解决问题的逻辑步骤顺序。
(2)伪代码:一种表达算法的语言。
6.5.1 伪代码的功能
(1)伪代码并非一种计算机语言,更像是一种人们用来说明操作的便捷语言。
(2)一些相关概念:
- 变量:出现在伪代码算法中的名字,引用的是内存中存储值的位置。这些名字要能反映出
它存放的值在算法中的角色。 - 赋值:把值存放入变量的方法。
- 输入/输出:从外部世界像计算机中输入数据值,还能把结果输入到屏幕上。
- 选择:用选择结构可以选择执行或跳过某项操作。此外,用选择结构还可以在两项操作之间进行选择。选择结构使用括号中的条件决定执行哪项操作。
- 重复:使用重复结构可以重复执行指令。
*代码旁边的IF或WHILE旁边的括号里的表达式是布尔表达式——评价为真或假的表达式
6.5.2 执行伪代码算法
本节以把十进制数字系统转化为其他进制数字的算法以伪代码的形式做例,执行了伪代码算法。
形式如下:
While(商不为0)
用新的基数除十进制数
余数作为结果中的最左边一位
用商替换原来的十进制数
6.5.3 写伪代码算法
(1)本节通过一个小规模的算法开发过程来说明使用的策略。
(2)桌面检查:在纸上走查整个设计
6.5.4 翻译伪代码算法
(1)如何翻译伪代码算法取决于我们将算法翻译成哪种语言。在这里,由于汇编语言的范围是有限的,所以一个伪代码语句需要几个Pep/8语句。
(2)本节通过交互式程序的编写对内容进行讲解。
6.6 测试
(1)测试程序的方法即执行程序。
(2)测试计划:说明如何测试程序的文档。
(3)代码覆盖(明箱)测试法:通过执行代码中的所有语句测试程序或子程序的测试方法。
(4)数据覆盖(暗箱)测试法:把代码作为一个暗箱,基于所有可能的输入数据测试程序或子程序的测试方法。
(5)测试计划实现:用测试计划中规定的测试用例验证程序是否输出了预期的结果。
第七章 问题求解与算法设计
7.1 如何解决问题
Polya的“如何解决它”列表:
- 必须理解问题
- 找到信息和解决方案之间的联系。如果找不到直接的联系,则可能需要考虑辅助问题。最终应该得到解决方案。
- 执行方案。
- 分析得到的解决方案。
7.1.1 提出问题
大意就是解决问题的前提是要提出问题,对设置的任务提出问题。
7.1.2 寻找熟悉的情况
(1)永远不要彻底重新做一件事。如果解决方案已经存在了,就用这种方案。如果以前曾经解决过相同或类似的问题,只需要再次使用那种成功的解决方案即可。
(2)识别相似的情况在计算领域内是非常有用的。在计算领域中,你会看到某种问题以不同的形式出现。
7.1.3 分治法
即把一项任务分成若干个子任务,而子任务还可以继续划分为子任务,如此进行下午。
可以反复利用分治法,直到每个子任务都是可以实现的为止。
7.1.4 算法
即在有限的时间内用有限的数据解决问题或子问题的明确指令集合。
7.1.5 计算机问题求解过程
计算机问题求解过程包含四个阶段:
- 分析和说明阶段
- 算法开发阶段
- 实现阶段
- 维护阶段
7.1.6 方法总结
1.分析问题
2.列出主要步骤
3.编写其余的模块
4.根据需要进行重组和改写
7.1.7 测试算法
需要在开发过程的更早阶段执行测试,特别是算法必须在实现之前进行测试。越早发现和修正问题,解决问题就越容易,代价也越小。
7.2 有简单参数的算法
7.2.1 带有选择的算法
使用Determine dress和IF语句进行带有选择的算法的编写。
7.2.2 带有循环的算法
(1)两种基本的循环:
- 计数控制循环:可以指定过程重复的次数,这个循环的机制是简单记录过程重复的次数并且在重复再次开始前检测循环是否已经结束。
有三个不同的部分,使用一个特殊变量叫做循环控制变量: - 初始化:循环控制变量初始化为某个初始值。
- 测试:循环控制变量是否已经达到特定值?
- 增量:循环控制变量以1递增。
*while循环被称为前测试循环,因为从循环前就开始测试了。 - 事件控制循环:循环中重复的次数是由循环体自身内发生的事件控制的循环。
使用while语句来实现事件控制循环时,这一过程仍分为三部分: - 事件必须初始化
- 事件必须被测试
- 事件必须更新
(2)计数控制循环是非常简单直接地,它指定了循环的次数。而在事件控制循环中则不太清楚,并不显而易见。
(3)嵌套结构:控制结构嵌入另一个控制结构的结构,又称为嵌套逻辑。
(4)平方根的计算:给出一个你想要计算的平方根的数,猜测一个可能的答案,然后把这个答案平方。如果你猜测的正确,这个平方根就等于原始值;如果不正确,则调整你的猜测,重新开始。这个过程一直进行,直到你猜测的平方根和原始值足够相近。
(5)抽象步骤:细节仍未明确的算法步骤。
具体步骤:细节完全明确的算法步骤。
7.3 复杂变量
7.3.1 数组
(1)数组是同构项目的有名集合,可以通过单个项目在集合中的位置访问他们。
项目在集合中的位置叫索引。多数程序语言从0开始。
(2)如果数组叫numbers,则通过表达式numbers[position]来访问数组中的每一个值,其中position就是索引,是一个从0到9之间的数。
(3)与数组相关的算法:
- 搜索:搜索数组中的项,一次寻找一个特定的值。
- 排序:按顺序将元素放入数组中。
- 处理:一种捕捉短语,包含了对数组中的项所做的所有其他计算。
7.3.2 记录
(1)记录是异构项目的有名集合,可以通过名字单独访问其中的项目。
所谓异构,就是指集合中的元素可以不必相同。
(2)记录可以把与一个对象相关的各种项目绑定在一起。
7.4 搜索算法
7.4.1 顺序搜索
我们依次查找每一个元素并将其与我们需要搜索的元素进行比较。如果匹配,则找到了这个元素;如果不匹配,则继续找下一个元素。
当我们发现了元素或者查找所有元素后都没有找到匹配项就停止。
7.4.2 有序数组中的顺序搜索
如果知道数组中的项目是有序的,那么在查找时,如果我们需要的项目在数组中,到了这个数可能在数组中的位置时就可以停止查找了。
7.4.3 二分检索
(1)二分检索采用的是分治法。
(2)二分检索指的是在有序列表中查找项目的操作,通过比较操作排除大部分检索范围。
(3)如果数组是有序的已经排好,且其中的项目不超过20个,那么使用二分检索算法更好。
7.5 排序
7.5.1 选择排序
(1)选择排序算法也许是最简单的,因为它与我们手动排序十分相似。
(2)缺陷:需要两个完整列表(数组)的空间。
不过对这种手动方法稍作修改,就可以免除所需的复制空间。
7.5.2 冒泡排序
(1)冒泡排序也是一种选择排序法,只是在查找最小值时运用了不同的方法。
它从数组的最后一个元素开始,比较相邻的元素对,如果下面的元素小于上面的元素,就交换这两个元素的位置。
(2)冒泡排序虽然效率低,但只要对它稍作修改,就能让它成为某些情况的最佳选择。
*选择排序算法不能确定数组是否是有序的,因此,一定要执行整个算法。
7.5.3 插入排序
将元素加入有序部分类似于冒泡排序中冒泡的过程。如果找到一个位置,要插入的元素比数组中这个位置的元素小,那么就将新元素插入这个位置。
7.6 递归算法
(1)当在一个算法中使用它自己时,这样的算法被称为递归算法。
也就是说,如果在某种程度上调用自己,则这个调用成为递归调用。
(2)递归就是算法调用它本身的能力,是另一种重复(循环)的控制结构。这种算法使用一个选择语句来确定是否重复算法来调用一遍或停止这一过程,而不是使用一个循环语句执行一个算法。
(3)每个递归算法至少有两种情况:
- 基本情况:答案已知的情况
- 一般情况:则是调用自身来解决问题的更小版本的解决方案。
因为一般情况下解决的是原始问题越来越小的版本,所以程序最终达到基本情况,及答案是已知的,所以递归停止。
(4)与每个递归问题相关的是如何衡量问题的大小。每次递归调用后,,问题都应该减小。所有递归解决方案的第一步都是确定尺寸系数。
7.6.1 子程序语句
(1)我们可以给一段代码一个名称,然后程序另一部分的一个语句使用这个名称。遇到这个名称时,这个进程的其他部分将会终止,等待这个命名代码被执行。当命名代码执行完毕,将会继续处理下面的语句。命名代码出现的地方被称为调用单元。
(2)子程序有两种形式:
- 只执行特定任务的命名代码:在调用单元中用作语句。
- 不仅执行任务,还返回给调用单元一个值(值返回子程序):用作表达式,返回的值被用来评估表达式。
(3)子程序是抽象的一种强力工具。命名的子程序列表允许程序的读者了解到任务已经完成并且不被任务实现的细节所打扰。如果一个子程序需要信息去执行他的任务,便把数据值的名字放在子程序标题的括号中。
7.6.2 递归阶乘
(1)数的阶乘的定义是这个数与0和它自身之间的所有数的乘积。0的阶乘是1.尺寸系数就是要计算阶乘的数。
(2)基本情况:Factorial(0)=1
一般情况:Factorial(N)=N*Factorial(N-1)
用if语句可以判断N是等于0(基本情况)还是大于0(一般情况)。显然每次调用N都会减小,所以一定能达到基本情况。
(3)每次调用Factorial时N都会减小,每次给出的数据称为参数。
子程序不断调用自身,直到运行时间支持系统耗尽了内存为止,这种情况叫做无限递归,与无限循环等价。
7.6.3 递归二分检索
递归算法必须从非递归算法中调用。
7.6.4 快速排列
(1)基本思想:对两个小列表排序比对一个大列表排序更快更容易。
(2)它的名字来源于这种算法通常可以相当快地对数据元素列表进行排序,其基本策略是“分治法”。
(3)如果数据是随机排列的,则快速排列是一个很好的排序方法;然而,如果数据已经排好,那么算法退化以保证每个分裂只有一个元素。
7.7 几个重要思想
7.7.1信息隐蔽
(1)信息隐蔽:隐蔽模块的细节以控制这些细节的访问的做法。即在进行高层设计时不能见到低层的细节。
(2)如果设计者知道一个模块的底层细节,ta就可能会以这些细节为基础设计这个模块的算法。但是这些低层的细节很可能会发生变化。一旦它们改变了,那么整个模块都要重写。
7.7.2 抽象
(1)抽象:复杂系统的一种模型,只包括对观察者来说必须的细节。
(2)数据抽象:把数据的逻辑视图和它的实现分离开。
过程抽象:把动作的逻辑视图和它的实现分离开。
控制抽象:把控制结构的逻辑视图和它的实现分离开.
控制结构:用于改变正常的顺序控制流的语句。
7.7.3 事物命名
(1)在编写算法时,我们使用速记短语表示要处理的任务和信息。也就是说,给数据和过程一个名字,这些名字叫做标识符。
(2)转换过程的两个阶段:
- 首先在算法中命名数据和动作。
- 然后把这些名字转换成符合计算机语言规则的标识符。
*数据和动作的标识符都是抽象的一种形式。
7.7.4 测试
两种基本的测试分类:
- 白盒测试:基于代码本身。
- 黑盒测试:基于测试所有可能的输入值。
浙公网安备 33010602011771号