跳至内容

A-level 计算机 2009/AQA/处理和编程技术/机器操作和汇编语言

来自维基教科书,开放的书籍,开放的世界

机器码

[编辑 | 编辑源代码]

机器码是一种二进制编程语言,是 CPU 最容易处理的形式。每行代码包含一个 **操作符**(指令的二进制表示)和一个 **操作数**(给定指令要操作的数据)。

汇编语言指令

[编辑 | 编辑源代码]

汇编语言是机器码和 **高级语言** 之间的中间阶段,通常可以通过直接翻译转换为机器码。与机器码一样,汇编语言指令包含操作符和一个或多个操作数。

每个处理器可用的确切指令范围将因处理器而异。但是,任何给定处理器都有四种不同类型的指令可用。

数据传输指令

[编辑 | 编辑源代码]

数据传输指令用于在 **寄存器** 之间以及寄存器和 **主内存** 之间移动数据。

算术指令

[编辑 | 编辑源代码]

算术指令可用于对寄存器内容执行算术函数。一些处理器允许使用多种算术指令,例如加法、减法、乘法、除法和增量。其他一些只允许加法和减法。

逻辑指令

[编辑 | 编辑源代码]

逻辑指令可用于对寄存器内容执行逻辑函数。逻辑指令的一些示例包括:and、or、xor 和 not。这些在掩码数字时很有用,例如将 ASCII 转换为数字的二进制表示或将 ASCII 从大写转换为小写。

只有当比较两个 1 时,答案才为 1。

只有当比较中存在一个或多个 1 时,答案才为 1。

或 EOR(异或/异或)
只有当比较中恰好有一个 1 时,答案才为 1。

将所有 1 变成 0,所有 0 变成 1。这对于二进制补码很有用。

屏蔽

[edit | edit source]

例如,将十进制数 3 的 ASCII 表示形式转换为二进制表示形式:十进制数 3 的 ASCII 表示形式为 。二进制表示形式为 。所以,为了从 ASCII 转换为二进制,我们需要屏蔽掉二进制表示形式的前四位,并保留后四位。有多种方法可以做到这一点。

AND solution

Note that we have set the last four bits to 1, try converting another ASCII number and see if this mask works for all of them?

XOR solution

Note that we only set the two bits different between the ASCII and binary to 1.  Try this mask for other ASCII numbers
Rules of Thumb
AND, if you want to keep a part of a number, AND 1 with it.  If you want to blank out part of a number, AND 0 with it.
OR, if you want to keep a part of a number, OR 0 with it.  If you want to set part of a number, OR 1 with it.
XOR, if you want to keep a part of a number, XOR 0 with it.  If you change a one to a zero XOR a 1 with it.

处理无关紧要

[edit | edit source]

考试可能会问你一些需要你为特定数字构建掩码的问题,检查 1 和 0,以及忽略某些单元格的内容。下面是一个快速参考表(X = 无关紧要的输入)

AND

如果你将除了所需输入以外的任何其他输入放入方程中,结果将不正确。你现在可以将它与数字 进行比较,如果相等,那么你就知道收到了正确的输入。

OR

如果你将除了所需输入以外的任何其他输入放入方程中,结果将不正确。你现在可以将它与数字 进行比较,如果相等,那么你就知道收到了正确的输入。

汇编中的示例

你只允许输入以下数字 ,编写一些汇编语言来检查它是否正常工作。

AND 1 0 1
CMP 0 0 1
BEQ label

尝试编写上述代码的 OR 版本。

移位操作

[edit | edit source]

如果你看一下以下数字的二进制表示形式,你会注意到一些奇怪的地方。

0001 = 1
0010 = 2
0100 = 4
1000 = 8

每次我们将数字向左移动一位,数字的值就会加倍。这不仅适用于一位,看看这个更复杂的例子。

0001 0101 = 21
0010 1010 = 42

同样,向左移动一位,数字就加倍了。另一方面,向右移动一位,数字就减半。

计算机在进行乘法和除法方面非常糟糕,它需要大量的 CPU 时间,并且会严重降低代码的速度。为了克服这个问题,计算机可以在寄存器中移动值,只要乘法或除法是 2 的幂,那么 CPU 时间就会减少,因为操作只需要一行机器代码。处理器可以执行三种主要的移位类型。

逻辑移位

[edit | edit source]

向左或向右移动,你在空的一端添加一个 0。

算术移位

[edit | edit source]

你保留被移动数字的符号位。通常只向右移动

请注意,逻辑移位示例也是算术移位的示例,因为符号保持不变

循环移位

[edit | edit source]

被推到一端的那一位出现在另一端。

测试和分支指令

[编辑 | 编辑源代码]

测试和分支指令用于测试给定条件是否为真,然后根据测试结果分支到给定指令。这使得条件语句和循环成为可能。

计算机指令

[编辑 | 编辑源代码]

计算机理解称为的指令。在计算环境中,字是指计算机一次可以执行的位数。你会遇到能够理解不同字长大小的处理器,例如,索尼 PlayStation 上的处理器字长为 32 位。索尼决定让 PlayStation 2 比初代产品更好,PlayStation 2 的字长为 128 位。一般来说,更大的字长意味着更快、更复杂的 CPU。

计算机能够理解的字由两部分组成。第一部分是指令类型,即操作码,第二部分包含指令将要执行的变量,即操作数。操作数有时称为地址,下一节将解释计算机如何以不同的方式使用操作数。

0 地址指令

[编辑 | 编辑源代码]

这种指令不接受任何参数,并涉及不需要变量的汇编代码。例如

  • CLC - 清除进位标志
  • EXIT - 退出子程序
  • INC - 将累加器加 1

1 地址指令

[编辑 | 编辑源代码]

当您只处理一个通用寄存器(累加器)时,这种指令非常有用,它只接受一个操作数。例如

  • LDA #34 - 将十进制值 34 加载到累加器中
  • ADD 234 - 将存储在内存地址 234 的值添加到累加器中

2 地址指令

[编辑 | 编辑源代码]

这种指令可以接受两个操作数,并且操作的复杂性也会增加。例如 ADD R1, R2 - 将 R1 加到 R2 并将结果存储回 R1

寻址格式

[编辑 | 编辑源代码]

处理器可以使用不同的方法来计算正在处理的指令或正在操作的数据的内存地址。这些被称为寻址模式

立即寻址

[编辑 | 编辑源代码]

这是您迄今为止一直使用的寻址模式,其中操作的数据在指令中给出。

例如:LDA #35; 将数字 35 立即加载到累加器中。

直接寻址

[编辑 | 编辑源代码]

在直接寻址中,数据的地址将在指令中给出。

例如:LDA 35; 将地址 35 的内容加载到累加器中。

间接寻址

[编辑 | 编辑源代码]

这类似于直接寻址,但是指令没有给出数据的地址,而是给出保存数据地址的地址。例如,如果内存地址 A0 包含“F1”,而内存地址 F1 包含“42”,那么要将 42 加载到累加器中,指令将是

LDA (&A0); 将地址 &A0 中给出的内容加载到累加器中

相对寻址

[编辑 | 编辑源代码]

这种寻址模式根据内存中的当前位置给出内存位置。

例如:JMP +10; 分支到距离当前指令 10 个字节的指令。

如果此指令位于地址 1,则它将跳转到地址 11。

基址寄存器寻址

[编辑 | 编辑源代码]

这种寻址模式将指定的地址与另一个位置保存的地址组合在一起。

LDA &12,B; 将 B 的内容与十六进制地址 12 相加,并将结果地址的内容加载到累加器中。

在此示例中,地址 &12 将添加到 B 中保存的地址,以找到要加载到累加器中的数据的地址。

索引寻址

[编辑 | 编辑源代码]

这种寻址模式类似于基址寄存器寻址,只是基址保存在索引寄存器中。如果使用这种寻址格式,则可以通过更改索引寄存器的内容来更改操作数的地址。

LDA TABLE,X; 将 TABLE + x 的内容加载到累加器中

一个帮你区分它们的故事

[编辑 | 编辑源代码]

曾经有一个名叫累加器的匪徒,很酷的名字,对吧?他参与了许多“生意”,需要相应地得到报酬。他喜欢用几种不同的方式获得报酬。这些方式分别是立即、直接、间接、索引和相对。

当他立即得到报酬时,他的打手会当场给他钱,他无需去寻找或解开任何谜题,他就立即得到钱。

“老板,这是 5 英镑” =
“LDA #5”

当他直接得到报酬时,他需要做一些工作,他在整个城市都有很多邮箱,他的客户会把付款丢在那里。他会得到一个特定邮箱的名称,并知道如果他去那里,他就能找到他想要的现金。他被直接引导到现金。

“老板,钱在地址 1023 的邮箱里”。
= “LDA 1023”

你必须明白,累加器还有其他做一些不正当生意的朋友,他们更喜欢在商业交易中尽可能地隐藏自己,以避免警察的追查。为此,他们使用了一个巧妙的系统,将钱放入邮箱,但没有直接告诉累加器地址,而是告诉累加器一个邮箱的地址,该邮箱包含真实邮箱的地址。他们间接地告诉了他地址。听起来有点混乱?别担心,希望这段简短的文字可以解决问题。

“老板,钱在哪里的地址在地址 304 的邮箱里”。
累加器打开地址 304 的邮箱,发现一张纸条,上面写着去 706。
当他到达 706 时,他找到了他想要找的钱。
= “LDA (304)”

对于一个匪徒来说,生意并不总是一帆风顺,有时他们必须解开一个或两个谜题才能拿到钱,就像电影里一样。在索引支付的情况下,累加器得到一个需要解决的线索,他知道基址,有人提供一个必须添加到基址的值。他将这两个值加在一起,然后他就找到了他应得的钱的存储地址。

“老板,你需要的基址是 7987”。
“老板,我们的消息来源说,你钱存放的房子距离基址 5 个房子”。
累加器在 7987 + 5(7992)中找到了他想要找的现金。
= LDA TABLE,X

汇编代码

[编辑 | 编辑源代码]

计算机只能理解 1 和 0。为了让计算机理解我们想要它做什么,我们必须将我们的想法转化为这些 1 和 0。你可以使用高级语言或低级语言汇编。在汇编代码中,每一行代码通常会转换成一行机器代码。汇编在工业中用于编程低级例程和函数,生成的代码通常简单但很长。

指令集

[编辑 | 编辑源代码]

指令集是 CPU 可以理解的不同指令的范围。有两种不同的思想流派,RISC 和 CISC。RISC - 精简指令集计算机可以执行的指令数量很少,但它通常执行得非常快且高效。CISC - 复杂指令集计算机可以执行的指令数量很多,但通常不如执行等效 RISC 代码的速度快。

为了考试,你需要了解 CPU 可以理解的一些基本汇编指令。我们现在将看看一些指令的范围,然后是一些使用它们的示例。

基本指令

[编辑 | 编辑源代码]
ADD #34
将一个数字添加到累加器并存储该值到累加器中
SUB #34
从累加器中减去一个数字并存储该值回累加器中
DEC
从累加器中减去 1
INC
向累加器加 1
LDA 34
将内存位置 34 中包含的值加载到累加器中
STO 34
将累加器的值存储到内存位置 34 中
CMP &34
将累加器与 34 的十六进制值进行比较,并将结果存储到状态寄存器中
BNE label1
如果比较结果不等于,则跳转到标签 label1
BEQ label1
如果累加器与被比较的值匹配,则跳转到标签 label1
BGT label1
如果累加器大于被比较的值,则跳转到标签 label1
BLT label1
如果累加器小于被比较的值,则跳转到标签 label1
JMP label1
直接跳转到标签 label1,类似于某些高级语言中的 goto 函数
AND 01001001
对累加器与值 01001001 进行“与”运算,并将结果存储到累加器中
OR 01001001
对累加器与值 01001001 进行“或”运算,并将结果存储到累加器中
XOR 01001001
对累加器与值 01001001 进行“异或”运算,并将结果存储到累加器中
对累加器进行“非”运算,并将结果存储回累加器中
MOV R1, R2
将寄存器 R1 的内容移动到寄存器 R2 中

在此处添加移位指令

你可能已经注意到,上面的一些命令要求程序“跳转”到名为 label1 的标签。这执行与 C 等语言中的 'goto' 语句相同的函数。虽然 goto 语句在高级语言中被认为是不可取的,但在汇编中,它对于执行循环和条件语句是必不可少的。标签在代码中将是这样的

LDA #40
label1
INC
CMP #46
BLT label1
STO 1024

这段代码将值 40 加载到累加器中。然后累加器加 1 并与数字 46 进行比较。如果累加器 **小于** 46,则跳转到标签 label1 以继续增加累加器。内存位置 1024 中将存储什么值?

在考试中,你经常会被要求取一段伪代码或真实代码并将其转换为汇编代码。为了确保考官知道你在做什么,请始终用代码编写注释。下面是一些伪代码及其汇编等效代码的示例

x = x + 1
LDA x
INC
INC
STO x
x = x + 1
while (x >= 6)
y = y + 4
end while
LDA x
while
LDA x
INC
INC
CMP #6
BLT end
LDA y
ADD #4

STO y

JMP while

end

快速检查问题

[编辑 | 编辑源代码]

提供将完成以下任务的汇编代码

y = x + y

计算给定二进制数 x 的负二进制补码并将结果存储回 x

将 ASCII 小写字母更改为其二进制等效值
Q3
[编辑 | 编辑源代码]
执行 x= x-1
华夏公益教科书