题2

题目

【2019 统考真题】已知 f(n) = n! = n × (n - 1) × (n - 2) × ⋯ × 2 × 1,计算 f(n) 的C语言函数 f1 的源程序 (阴影部分) 及其在 32 位计算机 M 上的部分机器级代码如下:

其中, 机器级代码行包括行号、虚拟地址、机器指令和汇编指令, 计算机 M 按字节编址, int 型数据占 32 位。请回答下列问题:

  1. 计算 f(10) 需要调用函数 f1 多少次? 执行哪条指令会递归调用 f1 ?
  2. 上述代码中, 哪条指令是条件转移指令?哪几条指令一定会使程序跳转执行?
  3. 根据第 16 行的 call 指令, 第 17 行指令的虚拟地址应是多少? 已知第 16 行的 call 指令采用 相对寻址方式, 该指令中的偏移量应是多少 (给出计算过程)? 已知第 16 行的 call 指令的后 4 字节为偏移量, M 是采用大端方式还是采用小端方式?
  4. f(13) = 6227020800,但 f1(13) 的返回值为1932053504,为什么两者不相等?要使 f1(13) 能返回正确的结果, 应如何修改 f1 的源程序?
  5. 第 19 行的 imul 指令 (有符号整数乘) 的功能是 R[eax] ← R[eax] × R[ecx],当乘法器输出的高、低 32 位乘积之间满足什么条件时, 溢出标志 OF=1?要使 CPU 在发生溢出时转异常处理, 编译器应在 imul 指令后加一条什么指令?

分析

题45

  1. 计算 需要调用函数 共 10 次,执行第 16 行的 call 指令会递归调用
  2. 第 12 行的 jle 指令是条件转移指令,其含义为小于或等于时转移,本行代码的意义为:当 时,跳转至地址 。第 16 行的 call 指令为函数调用指令,第 20 行的 jmp 指令为无条件转移指令,第 30 行的 ret 指令为子程序的返回指令,这三条指令一定会使程序跳转执行。
  3. 在计算机 M 上按字节编址,第 16 行的 call 指令的虚拟地址为 ,长度为 5 字节,因此第 17 行的指令的虚拟地址为 。第 16 行的 call 指令采用相对寻址方式,即目标地址 偏移量,call 指令的目标地址为 ,所以偏移量 = 目标地址 - (PC) = 00401000H - 0040102AH = FFFF FFD6H。根据第 16 行的 call 指令的偏移量字段为 D6 FF FF FF,可以确定 M 采用小端方式
  4. 因为 ,其结果超出了 32 位 int 型数据可表示的最大范围,因此 的返回值是一个发生了溢出的错误结果。为使 能返回正确结果,可将函数 的返回值类型改为 double(或 long long,或 long double,或 float)类型。
  5. 若乘积的高 33 位不全为 0 或不全为 1,则 。编译器应在 imul 指令后加一条“溢出自陷指令”,使得 CPU 自动查询溢出标志 OF,当 时调出“溢出异常处理程序”。