Appearance
题目
上题中 C 程序段在计算机 M 上的部分机器级代码如下,每个机器级代码行中依次包含指令序号、虚拟地址、机器指令和汇编指令。
for (i = 0; i < 24; i++)
1 00401072 C7 45 F8 00 00 00 00 mov[ebp-8], 0
2 00401079 EB 09 jmp 00401084h
3 0040107B 8B 55 F8 mov eax, [ebp-8]
... ... ...
7 00401088 7D 32 jge 004010bch
for (j = 0; j < 64; j++)
8 0040108A C7 45 FC 00 00 00 00 mov[ebp-4], 0
... ... ...
a[i][j] = 10;
... ... ...
19 004010AE C7 84 82 00 20 42 00 0A 00 00 00 mov[ecx+edx*4+00422000h], 0Ah
20 ... ...请回答下列问题。
(1) 第 20 条指令的虚拟地址是多少?
(2) 已知第 2 条 jmp 和第 7 条 jge 都是跳转指令,其操作码分别是 EBH 和 7DH,跳转地址分别为 0040 1084H、0040 10BCH,这两条指令都采用什么寻址方式?给出第 2 条指令 jmp 的跳转目标地址计算过程。
(3) 已知第 19 条 mov 指令的功能是“a[i][j]←10”,其中 ecx 和 edx 为寄存器名,0042 2000H 是数组 a 的首地址,指令中源操作数采用什么寻址方式?已知 edx 中存放的是变量 j,ecx 中存放的是什么?根据该指令的机器码判断计算机 M 采用的是大端还是小端方式。
(4) 第一次执行第 19 条指令时,取指令过程中是否会发生缺页异常?为什么?
解析
本题在 2023-43 的程序段之上看反汇编:考查 指令地址计算 / 跳转指令的相对寻址 / 寻址方式判别 / 字节序判定 / 缺页判定。
读 x86 反汇编要会做三件事:
- 由当前指令字节长度推下一条地址;
- 跳转指令的 target = (PC 取指后) + 偏移;
- 内存数据按小端序排列(x86 的标准)。
(1) 第 20 条指令的虚拟地址 [1 分]
第 19 条指令机器码 C7 84 82 00 20 42 00 0A 00 00 00,长度 11 字节。其起始地址 004010AEH:
(2) jmp / jge 的寻址方式 + jmp 目标地址 [3 分]
寻址方式:相对寻址。
x86 短跳指令编码 = [操作码 1 字节 | 8 位偏移],目标地址 = (PC 取指后) + 偏移(符号扩展)。
第 2 条 jmp 的目标地址计算:
- jmp 机器码
EB 09,长度 2 字节,起始地址00401079H; - PC 取指后 =
00401079H+ 2 =0040107BH; - 偏移 =
09H(正向 9 字节); - 目标地址 =
0040107BH+09H=00401084H。
与题给 00401084H 一致 ✓。
易错点: "PC + 偏移"中的 PC 是 取指完成后的 PC(即下一条指令的地址),不是 jmp 自身的地址。漏掉 +2 会算错。
(3) 第 19 条 mov 的寻址方式 + ecx 内容 + 字节序 [4 分]
Step 1. 源操作数寻址方式。
mov 把"立即数 0Ah"写到内存。源操作数 0Ah = 数值 10 → 立即(数)寻址方式。
Step 2. ecx 中存放的内容。
mov 的目的地址表达式:[ecx + edx*4 + 00422000H]。
题干说 edx 存放 j(变量),数组首地址 00422000H。比对 addr(a[i][j]) = 00422000H + i*256 + j*4:
编者注(生僻术语): 编译器把 a[i][j] 的地址计算分到两个寄存器:edx 装 j(每次循环 +1),ecx 装 i × 256(每次外层循环 +256)——这是 strength reduction 优化,把每个内循环的乘法换成加法。
Step 3. 字节序判定。
第 19 条机器码中包含 00 20 42 00(位移字段)和 0A 00 00 00(立即数字段)。
- 位移真值 =
00422000H,按位 [00, 00, 42, 00] 应该是 [低字节 → 高字节] = [00, 20, 42, 00]——与机器码一致; - 立即数真值 =
0000000AH,按位 [低 → 高] = [0A, 00, 00, 00]——与机器码一致。
低字节存于低地址 → 小端方式(little-endian)。
(4) 第一次执行第 19 条指令时取指是否缺页?[2 分]
不会缺页。
理由:
- 第 19 条指令地址
004010AEH,所在页00401H(高 20 位); - 该函数所有指令(第 1 至第 20 条)地址都在
00401000H ~ 004010FFH,统统在00401H这一页内; - 在执行到第 19 条之前,CPU 已经至少把第 1 条指令(同一页)加载进了主存——也即触发该页的缺页异常并把整页装入了主存;
- 因此第 19 条的取指请求该页已在主存中,直接命中,不缺页。
易错点: "执行第 19 条不会缺页"针对的是取指——即从主存读出指令本身。第 19 条访问的"数据"地址
00422100H等是另一回事,2023-43 第 (1) 问已分析数据缺页。两个问题不要混。