《汇编语言:基于X86处理器》第12章 复习题和练习
本篇记录了《汇编语言:基于X86处理器》第12章 复习题和练习的笔记。
12.6复习题和练习
12.6.1 简答题
1.假设有二进制浮点数1101.01101,如何将其表示为十进制分数之和?
答:1101.01101=(1x)+(1x
)+(0x
)+(1x
)+(0x
)+(1x
)+(1x
)+(1x
)+(1x
) = 13.40625
2.为什么十进制数0.2 不能用有限位数精确表示?
答:用有限位数表示的任何浮点数格式都无法表示完整连续的实数。 原因在于二进制和十进制小数转换时的数学限制
3.假设有二进制数 11011.01011,则其规格化数值为多少?
答:11011.01011 = 1.101101011×
4.假设有二进制数0000100111101.1则其规格化数值为多少?
答:0000100111101.1 = 1.001111011×
5.NaN 有哪两种类型?
答:NaN的两种类型为:quiet NaN能够通过大多数算术运行来传递,而不引 起异常。signaling NaN则被用于产生一个浮点无效操作异常。
6.FLD指令允许的最大数据类型是什么,它包含了多少位?
答:FLD指令允许的最大数据类型是REAL10,它包含80位。
7.FSTP 指令与FST指令有哪些不同?
答:FSTP指令与FST指令都是将浮点操作数从FPU栈顶复制到内存。不同点是FST复制完后不弹出堆栈,而FSTP保存到内存后将ST(0)弹出堆栈。
8.哪条指令能修改浮点数的符号?
答:FCHS(修改符号)指令将ST(0)中浮点数的符号取反。
9.FADD指令允许使用哪些类型的操作数?
答:m32fp,m64fp,和浮点寄存器操作数例如ST(0),ST(i), i是寄存器编号。
10.FISUB 指令与FSUB 指令有哪些不同?
答:FISUB和FSUB指令都是从目标操作数减去源操作数,FISUB是整数减法,先把源操作数转换为双精度浮点数,再从ST(0)中减去该操作数。
11.P6系列之前的处理器中,哪条指令可以比较两个浮点数?
答:FCOM指令可以比较两个浮点数。
12.哪条指令实现将整数操作数加载到ST(0)?
答:FILD指令实现将整数操作数加载到ST(0).
13.FPU控制字中的哪个字段可以修改处理器的舍入模式?
答:FPU控制字中的RC(位10和11)字段可以修改处理器的舍入模式。
12.6.2 算法基础
1.请写出二进制数+1110.011的IEEE 单精度编码。
答:+1110.011 = 1.110011× 符号位:0,偏移阶码:127+3 = 130 = 10000010b,小数部分23位,后面用0补齐11001100000000000000000,所以完整数的单精度编码为0 10000010 11001100000000000000000
2.将分数 5/8 转换为二进制实数。
答:5/8 = 1/2+1/8 = 1×+0×
+1×
= 0.101
3.将分数17/32 转换为二进制实数。
答:17/32 = 1/2+1/32=1×+0×
+0×
+0×
+1×
=0.10001
4.将十进制数+10.75 转换为IEEE 单精度实数。
答:+10.75 = 10+1/2+1/4 = 1010.11b规格化为1.01011×=》符号位:0,偏移阶码:127+3 = 130 = 10000010b,小数部分23位,后面用0补齐01011000000000000000000,所以完整数的单精度编码为0 10000010 01011000000000000000000
5.将十进制数 -76.0625 转换为 IEEE 单精度实数。
答:-76.0625 符号位为1,整数部分76转成二进制为01001100,小数部分.0625转成二进制
0.0625 × 2 = 0.125 → 0
0.125 × 2 = 0.25 → 0
0.25 × 2 = 0.5 → 0
0.5 × 2 = 1.0 → 1
从上往下读:0001
合并为01001100.0001,规格化为1.0011000001×,偏移阶码:127+6 = 133转成二进制为10000101b,符号位为1,所以组合成单精度实数为1 10000101 00110000010000000000000
6.编写含有两条指令的序列,将 FPU 状态标志送人 EFLAGS 寄存器。
答:fstsw ax ;将 FPU 的状态字(Status Word)存储到 AX 寄存器中。
;FPU 状态字包含条件码标志(C0-C3),这些标志对应于 EFLAGS 寄存器中的某些标志位。
sahf ;指令将 AH 寄存器的内容加载到 EFLAGS 的低字节
(具体对应关系如下):
- FPU 的 C0 对应 EFLAGS 的 CF(进位标志)
- FPU 的 C2 对应 EFLAGS 的 PF(奇偶标志)
- FPU 的 C3 对应 EFLAGS 的 ZF(零标志)
7.现有一个精确结果1.010101101,使用FPU默认舍入模式将该值舍人为8位有效数字。
答:FPU默认舍入模式是舍入到最接近的偶数。因此1.010101101的舍入结果为1.01010111
8.现有一个精确结果-1.010101101使用FPU默认舍入模式将该值舍人为8位有效数字。
答:FPU默认舍入模式是舍入到最接近的偶数。因此-1.010101101的舍入结果为-1.01010110
9.编写指令序列实现如下 C++代码:
double B = 7.8;
double M = 3.6;
double N = 7.1;
double P = -M * (N + B);
;12.2.9_1.asm 12.2.9 代码示例
;9.编写指令序列实现如下 C++代码:INCLUDE Irvine32.inc.data
B REAL8 7.8
M REAL8 3.6
N REAL8 7.1
P REAL8 ?.code
main PROCmov esi, OFFSET BFLD M ;ST(0) = MFLD N ;ST(0) = N, ST(1) = MFADD B ;ST(0)+B = 14.9FMUL ;ST(1)*ST(0) = 53.64 存放在ST(1),然后ST(0)出栈FCHS ;修改ST(0)的符号 -53.64FSTP P ;将 ST(0)保存到 PINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
10.编写指令序列实现如下C++代码:
int B = 7;
double N = 7.1;
double P = sqrt(N) + B;
;12.6.2_10.asm 12.6.2 算法基础
;10.编写指令序列实现如下C++代码:INCLUDE Irvine32.inc.data
B DWORD 7
N REAL8 7.1
P REAL8 ?.code
main PROCmov esi, OFFSET Bfld N ;ST(0) = Nfsqrt ;ST(0) = sqrt(N)fild B ;ST(0) = B, ST(1) = sqrt(N)FADD ;ST(0)+ST(1),结果存在ST(1),然后ST(0)弹出堆栈FSTP P ;将 ST(0)保存到 PINVOKE ExitProcess, 0
main ENDP
END main
运行调试:
11.给出如下MOV指令的操作码:
.data
myByte BYTE ?
myWord WORD ?
.code
mov ax, @data
mov ds, ax
mov es, ax ;a.8E
mov dl, bl ;b.8A
mov bl, [di] ;c.8A
mov ax, [si+2] ;d.8B
mov al, myByte ;e.A0
mov dx, myWord ;f.8B
答:a为8E, b为8A,c为8A,d为8B,e为A0,f为8B
12.给出如下 MOV 指令的 Mod R/M 字节:
.data
array WORD 5 DUP (?)
.code
mov ax, @data
mov ds, ax
mov BYTE PTR array, 5 ;a.
mov dx, [bp + 5] ;b.
mov [di], bx ;c.
mov [di + 2], dx ;d.
mov array[si + 2], ax ;e.
mov array[bx + di], ax ;f.
答:
13.手动汇编如下指令,并写出每条有标记指令的十六进制机器码字节序列。假设 vall 起始地址的偏移量为 0。使用 16 位数值时,字节序列必须按小端顺序呈现:
.data
val1 BYTE 5
val2 WORD 256.code
main PROCmov ax, 3h ;@data B8 03 00mov ds, ax ;a. 8E D8 mov al, val1 ;b. B0 05 mov cx, val2 ;c. B9 00 01mov dx, offset val1 ;d. BA 00 00mov dl, 2 ;e. B2 02mov bx, 1000h ;f. BB 00 10
debug验证, VS2019编译不了16位的汇编。