综合题

已知 f(n)=n!=n×(n-l)×(n-2)×…×2×1,计算 f(n)的 C 语言函数 fl 的源程序(阴影部分)及其在 32 位计算机 M 上的部分机器级代码如下:

问答题

计算 f(10)需要调用函数 f1 多少次?执行哪条指令会递归调用 f1?

【正确答案】

计算 f(10)需要调用函数 f1 共 10 次,执行第 16 行的 call 指令会递归调用 f1。

【答案解析】
问答题

上述代码中,哪条指令是条件转移指令?哪几条指令一定会使程序跳转执行?

【正确答案】

第 12 行的 jle 指令是条件转移指令,其含义为小于等于时转移,本行代码的意义为:当n≤1 时,跳转至地址 0040 1035H。第 16 行的 call 指令为函数调用指令,第 20 行的 jmp 指令为无条件转移指令,第 30 行的 ret 指令为子程序的返回指令,这三条指令一定会使程序跳转执行。

【答案解析】
问答题

根据第 16 行 call 指令,第 17 行指令的虚拟地址应是多少?已知第 16 行 call 指令采用相对寻址方式, 该指令中的偏移量应是多少(给出计算过程)?已知第 16 行 call 指令的后 4 字节为偏移量,M 采用大 端还是小端方式?

【正确答案】

其长度计算机 M 上按字节编址,第 16 行的 call 指令的虚拟地址为 0040 1025H,长度为 5 字节,故第 17 行的指令的虚拟地址为 0040 1025H + 5 = 0040 102AH。第 16 行的 call 指令采用相对寻址方式,即目标地址 = (PC) + 偏移量,call 指令的目标地址为 0040 1000H,所以偏移量=目标地址 - (PC) = 0040 1000H - 0040 102AH = FFFF FFD6H。根据第 16 行的 call 指令的偏移量字段为 D6 FF FF FF,可以确定 M 采用小端方式。

【答案解析】
问答题

f(13)=6 227 020 800,但 f1(13)的返回值为 1 932 053 504,为什么两者不相等?要使 f1(13)能返回正 确的结果,应如何修改 f1 源程序?

【正确答案】

因为 f(13) = 6227020800,其结果超出了 32 位 int 型数据可表示的最大范围,因此 f(13)的返回值是一个发生了溢出的错误结果。为使 f1(13)能返回正确结果,可将函数 f1 的返回值类型改为 double(或 long long,或 long double,或 float)类型。

【答案解析】
问答题

第 19 行 imul eax,ecx 表示有符号数乘法,乘数为 R[eax]和 R[ecx],当乘法器输出的高、低 32 位乘积 之间满足什么条件时,溢出标志 OF=1?要使 CPU 在发生溢出时转异常处理,编译器应在 imul 指令 后加一条什么指令?

【正确答案】

若乘积的高 33 位为非全 0 或非全 1,则 OF = 1。编译器应在 imul 指令后加一条“溢出自陷指令”,使得 CPU 自动查询溢出标志 OF,当 OF = 1 时调出“溢出异常处理程序”。

【答案解析】