计组习题的那些事(2)

今天起床,感觉十分通透啊,是个不错的日子!!!

注意这一章一般不会考察程序的书写,因此重点放在寻址和一些基本概念。

问题:

  1. 是否能通过某个存储单元中的二进制模式确定其是机器指令还是数字?
  2. 在一台按字节寻址并使用大端策略的计算机上,输入单词 "Computer" 并存储到从单元 1000 开始的存储器中,说明单元 1000 和 1004 中两个存储字的内容。

答案:

2.1 能否通过二进制模式区分机器指令和数字?

  1. 回答:
    • 不能。因为任何二进制模式可以既被解释为一个数字,也可以被解释为一条机器指令。
    • 其含义取决于上下文:处理器如何解释存储器中的模式由执行的程序和当前操作决定。
  2. 解释:
    • 二进制模式没有内在区分是否为数字或指令的标记,只有在特定语义下才被赋予含义。例如:
      • 如果模式被加载到寄存器中进行算术运算,它可能被当作数字处理。
      • 如果模式被解释为 CPU 的操作码及其操作数,它就是一条机器指令。

2.2 存储单词 "Computer" 时存储器内容的表示

  1. 背景信息:

    • 按字节寻址: 每个存储地址对应一个字节(8 位)。

    • 大端策略: 高位字节存储在低地址,低位字节存储在高地址。

    • 单词 "Computer" 的 ASCII 表示如下(十六进制):

      1
      C = 43, o = 6F, m = 6D, p = 70, u = 75, t = 74, e = 65, r = 72
  2. 存储内容:

    • 存储器从地址 1000 开始按字节存储字符:

      1
      2
      地址: 1000    1001    1002    1003    1004    1005    1006    1007  
      内容: 43 6F 6D 70 75 74 65 72
    • 每个 32 位字 包含 4 个字节。根据大端规则:

      • 单元 1000 的字内容为:43 6F 6D 70
      • 单元 1004 的字内容为:75 74 65 72
  3. 结果:

    • 单元 1000 的存储字内容(十六进制):436F6D70
    • 单元 1004 的存储字内容(十六进制):75746572

总结:

  1. 二进制模式的含义取决于上下文,无法单独通过模式确定它是数字还是指令。
  2. 输入单词 "Computer" 时:
    • 单元 1000 的内容是 436F6D70
    • 单元 1004 的内容是 75746572

问题:

以下两个语句段都可以将值 300 存储在单元 1000 中,但完成的时间不同:

1
2
ORIGIN 1000  
DATAWORD 300
1
2
3
R2 ← #1000  
Move R3, #300
Store R3, (R2)

请解释这种差异。


答案:

  1. 第一种方法:
    • 指令含义:
      • ORIGIN 1000: 指示程序将数据存储的起始地址设置为 1000。
      • DATAWORD 300: 在位置 1000 中存储数据值 300。
    • 实现时间:
      • 这是一种 汇编器指令,作用于程序的编译和加载阶段。
      • 在程序加载到内存时,值 300 就已经存储在地址 1000 中,无需执行任何额外的机器指令。
    • 过程特性:
      • 存储操作在 程序运行之前 完成。
      • 值 300 在程序加载到内存时静态地放入单元 1000 中。
  2. 第二种方法:
    • 指令含义:
      • R2 ← #1000: 将值 1000 加载到寄存器 R2 中。
      • Move R3, #300: 将值 300 加载到寄存器 R3 中。
      • Store R3, (R2): 将寄存器 R3 中的值存储到 R2 指定的内存地址(1000)。
    • 实现时间:
      • 这些是 运行时指令,必须在程序运行时逐条执行。
      • 值 300 只有在这些机器指令执行完后才会存储到地址 1000。
    • 过程特性:
      • 存储操作在 程序运行时 执行,由机器指令动态完成。

差异总结:

  1. 存储时机:
    • 第一种方法在程序加载到内存时完成存储;
    • 第二种方法在程序运行时通过指令动态完成存储。
  2. 实现方式:
    • 第一种方法是 汇编器指令,依赖汇编器在程序加载时设置数据内容;
    • 第二种方法是 机器指令,由 CPU 在程序运行时逐条执行完成操作。
  3. 灵活性:
    • 第一种方法用于静态数据初始化,不适合动态存储需求;
    • 第二种方法更灵活,适用于动态计算和存储操作。

问题:

关于递归与嵌套,堆栈是最万能的。

子程序的返回地址可保存在以下哪种方式中?这些方式支持子程序嵌套和递归吗?

  1. (a) 处理器的寄存器中
  2. (b) 一个与调用有关的存储单元中(即,不同调用使用不同存储单元)
  3. (c) 一个堆栈中

答案:

  1. (a) 处理器的寄存器中:
    • 返回地址存储方式: 子程序的返回地址存储在固定的寄存器中。
    • 支持情况:
      • 嵌套: 不支持。嵌套调用会覆盖寄存器中的返回地址,导致无法正确返回上一层调用。
      • 递归: 不支持。递归调用时,每次调用都会覆盖寄存器中的返回地址,返回行为将出错。
  2. (b) 与调用有关的存储单元中:
    • 返回地址存储方式: 每次调用子程序时,返回地址存储在一个特定的存储单元中,不同调用使用不同的单元。
    • 支持情况:
      • 嵌套: 支持。不同的调用会使用不同的存储单元,嵌套调用的返回地址不会互相干扰。
      • 递归: 不支持。递归调用会多次使用同一个子程序,如果返回地址仅存储在单独的固定存储单元中,将导致后续返回地址被覆盖。
  3. (c) 一个堆栈中:
    • 返回地址存储方式: 每次调用子程序时,返回地址压入堆栈;返回时,从堆栈弹出地址进行跳转。
    • 支持情况:
      • 嵌套: 支持。堆栈按照“后进先出”规则管理返回地址,确保嵌套调用的每一层都能正确返回。
      • 递归: 支持。每次递归调用会将返回地址压入堆栈,递归完成时逐一弹出返回地址,支持递归逻辑。

总结:

  • (a) 寄存器: 不支持嵌套,也不支持递归。
  • (b) 存储单元: 支持嵌套,但不支持递归。
  • (c) 堆栈: 支持嵌套,也支持递归。

原因: 堆栈的动态性和分层管理特性,使其能够同时支持嵌套调用和递归调用,这是子程序返回地址管理的最通用方式。