是什么
-
定义:控制流转移指令通过修改程序计数器(PC)改变指令执行流;相对寻址以当前指令下一条地址为基准加上偏移量定位目标;溢出异常处理是硬件检测到计算超出表示范围后通过软硬件协同转向异常处理程序。
-
大白话:条件转移是“满足条件才拐弯”,无条件转移是“走到这就必须拐弯”;相对寻址是“从下一条指令的位置往前或往后走几步”;大小端是“多字节数据的高低位在内存里谁前谁后”;乘法溢出是“高位没能成为低位的纯符号复制品,说明有效数据被挤出去了”。
==下一条指令的地址 = 当前指令首地址 + 当前指令机器码长度==
核心内容
1. 转移指令分类与判别
| 类别 | 定义与触发机制 | 常见汇编指令 | 408 判别抓手 |
|---|---|---|---|
| 条件转移指令 | 必须检查标志位( 等),条件满足才修改 PC,不满足则顺序执行下一条 | jle(小于等于)、jl(小于)、jge(大于等于)、jg(大于)、je/jz(等于/为零)、jne/jnz(不等于)、jc/jnc(进位/无进位)、jo/jno(溢出/无溢出) | 指令助记符以 j 开头且后面跟有条件后缀(如 le, z, o 等) |
| 一定会转移的指令(无条件改变控制流) | 不需要检测任何标志位,执行到该指令必然修改 PC 跳转 | 1. 无条件跳转:jmp(直接跳到目标)2. 子程序调用: call(保存返回地址并跳到函数入口)3. 子程序返回: ret(从栈顶弹出返回地址给 PC)4. 中断/异常返回: iret | 只要执行,PC 就绝对不会自然自增到下一条指令 |
2. PC 相对寻址与 408 核心寻址方式对比
相对寻址(Relative Addressing)
-
公式:
-
关键定义:== 的值永远是当前指令的下一条指令的虚拟地址==(因为在 CPU 取出当前指令后,硬件会自动执行 )。
题目中 `EB 09` 和 `7D 32`,操作码是EBH和7DH,所以其中 `09` 和 `32` 是偏移量,
-
偏移量计算公式:
-
机器表示:若偏移量为负数,必须转换为补码形式存储。
408 常见寻址方式有效地址(EA)计算汇总
其中A是偏移量,注:
-
算术运算指令时(如
addi):-
-
这里的 是参与加法计算的立即数(操作数本身)。
-
-
当它是访存指令时(如本题的
lw):-
-
这里的 充当了基址寻址中的偏移量 ,与寄存器 里的基地址相加,合成有效地址 。
-
| 寻址方式 | 有效地址 EA 公式 | 核心应用场景 |
|---|---|---|
| 直接寻址 | 访问全局变量 / 固定地址 | |
| 寄存器间接寻址 | 指针访问 | |
| 基址寻址 | 多道程序、局部变量(以 ebp 为基址) | |
| 变址寻址 | 数组遍历、循环访问连续空间 | |
| 相对寻址 | 代码内部的分支跳转、函数调用 |
3. 大端方式 vs 小端方式判定
-
大端方式(Big-Endian):数据的高位字节存放在内存的低地址端(先存高位,符合人类阅读习惯)。(
0x12345678就是数据,而12345678就是内存排序,相同的) -
小端方式(Little-Endian):数据的低位字节存放在内存的低地址端(先存低位,x86 / ARM 常见)。
快速判别法则(直接两者对比,一样就是大端,相反就是小端)
以 32 位十六进制数 0x12345678(其中 12 是最高有效字节 MSB,78 是最低有效字节 LSB)存放在起始地址 00401000H 为例:
Plaintext
地址顺序从低到高:00401000H 00401001H 00401002H 00401003H
小端存储顺序: 78 56 34 12 (低位在低地址)
大端存储顺序: 12 34 56 78 (高位在低地址)
在机器指令中看偏移量字节顺序:若数值为 0xFFFFFFD6,在机器码中排列为 D6 FF FF FF,低位 D6 出现在最前面的低地址,必为小端方式。
4. 乘法溢出判定(为什么高 32 位不全为 0 且不全为 1 时 ?)
两个 32 位数相乘,ALU 会输出 64 位乘积(高 32 位与低 32 位): 在不溢出的情况下,高 32 位全部 32 个 bit,本质上就是低 32 位最高位(符号位)的“完全复制品
-
计算机存放机制:通常只把低 32 位写回通用寄存器。如果高 32 位包含了运算的有效数据,说明这部分数据被截断丢失了,即发生溢出()。
-
有符号数的符号扩展规则:
-
若真实结果为正数(低 32 位最高位为 0),没有溢出时,高 32 位应该全部补 0(全 0)。
-
若真实结果为负数(低 32 位最高位为 1),没有溢出时,高 32 位应该全部补 1(全 1,补码符号扩展)。
-
-
核心结论:
-
==未溢出()== 高 32 位与低 32 位的符号位完全一致(高 32 位全 0 且低 32 位最高位为 0,或高 32 位全 1 且低 32 位最高位为 1)。
-
==溢出()== 高 32 位不全为 0 且不全为 1,或者高 32 位虽全 0/全 1 但与低 32 位的最高符号位不一致。
-
区分 与
乘法里的溢出:对有符号乘法看 ;对无符号乘法看 (无符号乘法高 32 位只要不全为 0,即 )。
关注的是符号位截断导致的数值失真,而不是加法中的进位。
5. 溢出异常处理:是不是所有溢出都加 into?
-
into指令的专属性:into(Interrupt on Overflow)是 x86 架构专属的溢出中断指令。它的硬件逻辑是:==检测标志位 ,若 则触发 4 号中断/异常;若 则相当于空操作(NOP)==。 -
其他架构/常见处理方式:
-
其他指令集(如 MIPS/RISC-V):没有
into指令。MIPS 提供了带溢出捕获的算术指令(如add,sub),硬件直接触发异常;不带捕获的指令(addu,subu)则忽略溢出。 -
条件分支跳转(软件模拟):使用
jo Target(若溢出则跳转到异常处理程序),该方式在所有 CISC/RISC 架构中通用。
-
-
408 考点定位:考查 x86 汇编中“在算术指令后紧跟一条什么指令可让 CPU 转异常处理”时,标准答案为 ==
into==(或写jo指令跳转)。
例题
-
题目:
已知 ,计算 的 C 语言函数及其在 32 位计算机 M 上的部分机器级代码如下:
C
int f1(int n) { if (n > 1) return n * f1(n - 1); else return 1; }代码段
; 行号 虚拟地址 机器指令 汇编指令 1 00401000 55 push ebp ... 11 00401018 83 7D 08 01 cmp dword ptr [ebp+8], 1 12 0040101C 7E 17 jle 00401035H 13 0040101E 8B 45 08 mov eax, dword ptr [ebp+8] 14 00401021 83 E8 01 sub eax, 1 15 00401024 50 push eax 16 00401025 E8 D6 FF FF FF call 00401000H ... 19 00401030 0F AF C1 imul eax, ecx 20 00401033 EB 05 jmp 0040103AH 21 00401035 B8 01 00 00 00 mov eax, 1 ... 30 0040104A C3 ret-
上述代码中,哪条指令是条件转移指令?哪几条指令一定会使程序转移执行?
-
根据第 16 行的
call指令,第 17 行指令的虚拟地址是多少?已知第 16 行采用相对寻址方式,该指令中的偏移量是多少?M 是采用大端方式还是小端方式? -
第 19 行的
imul指令中,当乘法器输出的高、低 32 位乘积之间满足什么条件时,溢出标志 ?要使 CPU 在发生溢出时转异常处理,编译器应在imul指令后加一条什么指令?
-
-
分析:
-
条件转移看标志位,仅第 12 行
jle;无条件改变流向包含call(16 行)、jmp(20 行)、ret(30 行)。 -
第 16 行占 5 字节,下条指令地址为 。偏移量 。机器码为
D6 FF FF FF,低字节在低地址,为小端。 -
32 位带符号乘法溢出即高 32 位不是低 32 位的符号位扩展(不全为 0 且不全为 1)。x86 下配合使用
into指令触发中断。
-
-
答案:
1)
-
条件转移指令:第 12 行指令(
jle)。 -
一定会使程序转移执行的指令:第 16 行(
call)、第 20 行(jmp)、第 30 行(ret)。
2)
-
第 17 行指令的虚拟地址:
-
偏移量计算:
-
大小端判断:
偏移量
FFFFFFD6H的最低有效字节D6H存放在最低地址端,因此 M 采用小端方式。
3)
-
条件:乘法器输出的高 32 位不全为 0 且不全为 1(或高 32 位不是低 32 位的符号扩展)时,。
-
添加指令:
into(或jo跳转到异常处理程序)。
-
⚠️ 易错点
Warning
相对寻址 PC 计算基准错误 → 绝不能用当前指令首地址相减。必须用 (即下一条指令的虚拟地址)作为被减数基准。
漏认转移指令中的
call和ret→call和ret在本质上都是无条件转移指令(强制改写 PC),不要只盯着jmp。有符号数乘法与加法溢出的区别 → 加法溢出看最高位与次高位进位();乘法产生双倍字长积,溢出看的是高半部分是否破坏了符号扩展。