以下是根据文档整理的汇编课程知识点:
重点难点概述
- 布尔指令与比较指令的使用方法及功能
学习如何使用常见的布尔指令(and
、or
、not
、xor
、test
)以及比较指令(cmp
),并理解它们的作用和应用。 - 标志寄存器与各标志位的关联
掌握各指令与标志寄存器中的标志位(如溢出标志OF
、方向标志DF
、中断标志IF
、符号标志SF
、零标志ZF
、辅助进位标志AC
、奇偶标志PE
、进位标志CY
)之间的关系,学会如何通过标志位的状态判断程序执行情况。
条件分支概念
- 条件分支
条件分支是用于决策和控制程序流的机制。在高级语言中通过if
、switch
、for
、while
等语句实现条件判断与流程控制,而在汇编语言中,虽然没有直接的语句支持,但可以通过条件跳转指令实现类似功能。 - 硬件控制中的位操作
在硬件设备的控制中,常常需要操作数字的特定位,如测试、清除、置位等。汇编语言通过操作特定的标志位或数据位,来实现如电机启动、机器复位等硬件控制功能。
布尔指令与比较指令
- 布尔指令
and
** 指令**:对两个操作数进行按位与操作。清零,交集
示例:将字符'a'
(01100001
)转换为'A'
(01000001
),可以使用以下指令:
mov al, 01100001b ; AL = 'a'
and al, 11011111b ; AL = 'A'
- `or`** 指令**:对两个操作数进行按位或操作。并集
示例:
mov al, 1110011b ; AL = 1110011
or al, 00000100b ; AL = 11100111
- `not`** 指令**:对操作数进行按位取反操作。补集
示例:
mov al, 11110000b ; AL = 11110000
not al ; AL = 00001111
- `xor`** 指令**:对两个操作数进行按位异或操作,相同为 0,不同为 1。
示例:
mov al, 10101010b ; AL = 10101010
xor al, 11001100b ; AL = 01100110
- `test`** 指令**:与 `and` 类似,但不改变目标操作数,常用于测试某些位。
示例:
test al, 00001001b ; 测试 AL 中的位 0 和位 3
; ZF = 1 (如果测试结果为 0),否则 ZF = 0
- **比较指令 **
cmp
cmp
用于比较源操作数与目标操作数。其通过将目标操作数减去源操作数,并根据结果更新标志位ZF
、CF
、OF
来判断两者的关系。
示例:
mov ax, 1000h ; AX = 1000h
mov cx, 1000h ; CX = 1000h
cmp cx, ax ; 比较 CX 和 AX
; ZF = 1,表示两者相等
标志位操作
- **改变零标志位 **
ZF
使用以下指令可改变零标志位的值:test al, 0
(零标志位置 1)and al, 0
(零标志位置 1)or al, 1
(零标志位清零)
- **改变符号标志位 **
SF
- 使用
or al, 80h
可将符号标志位置为 1。 - 使用
and al, 7Fh
可将符号标志位清零。
- 使用
- **改变进位标志位 **
CF
stc
指令将进位标志位置为 1。clc
指令将进位标志位清零。
- **改变溢出标志位 **
OF
- 例如,
mov al, 7Fh
,inc al
后AL
为80h
,此时溢出标志位OF
会被设置为 1,表示发生了溢出。 - 使用
or eax, 0
可将溢出标志位清零。
- 例如,
重点难点
- 理解条件跳转的原理及应用
掌握不同类型条件跳转指令的使用条件和功能。学习如何通过比较指令(如CMP
)和标志位操作,结合条件跳转指令实现不同的流程控制。
条件跳转原理
- 高级语言与汇编语言中的条件判断
在高级语言中,条件判断通常通过if
、switch
等语句实现,而在汇编语言中,则通过比较指令(如CMP
、AND
、SUB
等)先改变标志位,再通过条件跳转指令根据标志位的状态决定是否跳转。
示例:
mov eax, 0 ; 将 0 赋值给 EAX
cmp eax, 0 ; 比较 EAX 和 0
jz L1 ; 如果 EAX 为 0,跳转到 L1
- **步骤**:1. 使用 `CMP`、`AND`、`SUB` 等指令改变标志位。2. 使用条件跳转指令(如 `JZ`、`JE` 等)检查标志位,根据条件决定是否跳转。
Jcond指令类型
- 基于特定标志位的值跳转
根据标志位的状态决定是否跳转。常见的条件跳转指令包括:
示例:
mov ax, 5
cmp ax, 4
je L1 ; 如果 ax == 4,跳转
jl L2 ; 如果 ax < 4,跳转
- `JZ`:当零标志位(ZF)为 1 时跳转(等于 0)。
- `JNZ`:当零标志位(ZF)为 0 时跳转(不等于 0)。
- `JC`:当进位标志位(CF)为 1 时跳转(有进位)。
- `JNC`:当进位标志位(CF)为 0 时跳转(无进位)。
- `JO`:当溢出标志位(OF)为 1 时跳转(溢出)。
- `JNO`:当溢出标志位(OF)为 0 时跳转(无溢出)。
- `JS`:当符号标志位(SF)为 1 时跳转(负数)。
- `JNS`:当符号标志位(SF)为 0 时跳转(非负数)。
- `JP`:当偶校验标志位(PF)为 1 时跳转(偶校验)。
- `JNP`:当偶校验标志位(PF)为 0 时跳转(奇校验)。
- 基于两数是否相等,或是否等于 ECX 寄存器的值跳转
跳转指令包括:(E 等于)
示例:
mov edx, 0A523h
cmp edx, 0A523h
je L1 ; 如果相等,跳转
jne L5 ; 如果不相等,跳转
- `JE`:相等跳转(`leftOp == rightOp`)。
- `JNE`:不相等跳转(`leftOp ≠ rightOp`)。
- `JCXZ`:当 `CX = 0` 时跳转。
- `JECXZ`:当 `ECX = 0` 时跳转。
- `JRCXZ`:当 `RCX = 0` 时跳转(64 位模式)。
- 基于无符号操作数的比较跳转
这些指令用于无符号数的比较:【 A 大于,B 小于】
示例:
mov ax, 5
cmp ax, 4
ja L1 ; 如果 ax > 4,跳转
jb L2 ; 如果 ax < 4,跳转
- `JA`:大于跳转,若 `leftOp > rightOp`。
- `JB`:小于跳转,若 `leftOp < rightOp`。
- `JAE`:大于或等于跳转,若 `leftOp ≥ rightOp`。
- `JBE`:小于或等于跳转,若 `leftOp ≤ rightOp`。
- `JNBE`:不小于或等于跳转,与 `JA` 相同。
- `JNAE`:不大于或等于跳转,与 `JB` 相同。
- 基于有符号操作数的比较跳转
这些指令用于有符号数的比较:【G 大于,L 小于】
示例:
mov al, 127 ; AL = +127
cmp al, -128 ; 比较 AL 和 -128
ja IsAbove ; 跳转,因 +127 < -128(不跳转)
- `JG`:大于跳转,若 `leftOp > rightOp`。
- `JL`:小于跳转,若 `leftOp < rightOp`。
- `JGE`:大于或等于跳转,若 `leftOp ≥ rightOp`。
- `JLE`:小于或等于跳转,若 `leftOp ≤ rightOp`。
- `JNLE`:不小于或等于跳转,与 `JG` 相同。
- `JNGE`:不大于或等于跳转,与 `JL` 相同。
条件循环指令
类似于 while,这里需要判断 ECX 循环次数和 ZF 条件
LOOPZ
** /LOOPE
指令**
执行ECX = ECX - 1
操作,如果ECX > 0
且ZF = 1
,则跳转到目标地址。- 用于判断循环次数并且
ZF
为 1 时跳转。
- 用于判断循环次数并且
LOOPNZ
** /LOOPNE
指令**
执行ECX = ECX - 1
操作,如果ECX > 0
且ZF = 0
,则跳转到目标地址。- 用于判断循环次数并且
ZF
为 0 时跳转。
- 用于判断循环次数并且
条件结构概述
- 条件结构的作用
条件结构用于在不同的逻辑分支中依据条件表达式做出选择。在高级语言中,通常使用if...else
等语句来实现,而在汇编语言中,需要将这些高级语言的条件结构转化为低级语言实现。理解汇编语言中如何实现条件结构是学习汇编的重要基础。
汇编实现条件结构的方式(事例分析)
- 一个分支情况
- 对于高级语言中的
if(op1 == op2) { X = 1; Y = 2; }
,在汇编中实现时,先将op1
送入eax
寄存器,然后通过cmp eax, op2
来比较op1
和op2
。若相等,则执行mov X, 1
和mov Y, 2
;若不相等,则跳过赋值指令。 - 使用
jne
指令表示“不相等”时跳转,或者使用je
指令表示“相等”时跳转到特定标签进行赋值操作。
- 对于高级语言中的
汇编实现:
mov eax, op1 ; 将 op1 送入 eax 寄存器
cmp eax, op2 ; 比较 eax 和 op2
je L1 ; 如果相等,跳转到 L1 进行赋值
; 如果不相等,跳过赋值操作
jmp L2 ; 跳过赋值操作
L1:
mov X, 1 ; 执行赋值 X = 1
mov Y, 2 ; 执行赋值 Y = 2
- 两个分支情况
- 对于
if (op1 > op2) call Routine1 else call Routine2
,首先将op1
送入eax
寄存器,使用cmp eax, op2
比较op1
和op2
,若op1 > op2
(jg A1
),则调用Routine1
,并跳转到A2
结束;若不满足条件,则调用Routine2
。
- 对于
汇编实现:
mov eax, op1 ; 将 op1 送入 eax 寄存器
cmp eax, op2 ; 比较 op1 和 op2
jg Routine1 ; 如果 op1 > op2,跳转调用 Routine1
call Routine2 ; 否则调用 Routine2
- 分支嵌套情况
- 对于
if op1 == op2 { if X > Y call Routine1 else call Routine2 } else call Routine3
,首先比较op1
和op2
,若不相等则跳转到调用Routine3
;如果相等,则进一步比较X
和Y
,根据比较结果调用Routine1
或Routine2
。
- 对于
汇编实现:对于嵌套可以使用不符合条件跳转(跳过{}中执行逻辑),符合条件往下执行{}。
mov eax, op1
cmp eax, op2
jne Routine3 ; 如果 op1 不等于 op2,跳转调用 Routine3
; 如果 op1 == op2,继续判断 X 和 Y
mov eax, X
cmp eax, Y
jg Routine1 ; 如果 X > Y,调用 Routine1
call Routine2 ; 否则调用 Routine2
- while 循环情况
- 对于
while(val1 < val2) { val1++; val2--; }
,首先将val1
复制到eax
,在循环中通过cmp eax, val2
判断val1
是否小于val2
,若不小于则退出循环。否则执行val1++
和val2--
操作,跳转到循环的起始位置继续判断。
- 对于
汇编实现:对于循环用不符合条件跳转(跳过{}中执行逻辑),符合条件往下执行{}。同时在{}最后执行一个 jmp 无条件跳转回判断处
beginwhile:
mov eax, val1 ; 将 val1 赋值给 eax
cmp eax, val2 ; 比较 val1 和 val2
jnl endwhile ; 如果 val1 >= val2,跳出循环
inc eax ; val1++
mov val1, eax ; 更新 val1
dec val2 ; val2--
mov eax, val2 ; 更新 val2
jmp beginwhile ; 跳转回循环开始处
endwhile:
符合表达式与短路求值
- 短路求值
对于复杂的条件表达式,如if (al > b1) AND (b1 > c1)
,采用短路求值的方式。首先判断第一个条件al > b1
,若为假(即cmp al, b1
不成立),则跳过后续的判断操作。若第一个条件为真,则继续判断第二个条件b1 > c1
,只有两个条件都为真时才执行后续操作(如mov X, 1
)。
汇编实现:
cmp al, b1 ; 比较 al 和 b1
jna L1 ; 如果 al <= b1,跳过后续操作
cmp b1, c1 ; 如果 al > b1,继续比较 b1 和 c1
jna L1 ; 如果 b1 <= c1,跳过后续操作
mov X, 1 ; 执行后续操作
L1:
表驱动选择【没掌握】
- 表驱动方法
使用查表方式代替多路选择。首先建立一个查找表,包含查询值(如字符)及对应的子程序偏移量。通过查找表中对应项来确定执行的子程序。可以通过计算表项大小(EntrySize = ($ - CaseTable)
)和表项数量来遍历和操作表。
汇编实现:
INCLUDE Irvine32.inc
.data
CaseTable BYTE 'A' ;查询值DWORD Process_A ;过程地址
EntrySize = ($ - CaseTable)BYTE 'B'DWORD Process_BBYTE 'C'DWORD Process_CBYTE 'D'DWORD Process_D
NumberOfEntries = ($ - CaseTable) / EntrySize
prompt BYTE "Press capital A,B,C,or D :",0
有限状态机(FSM)【没掌握】
- 概念
有限状态机(FSM)是根据输入改变状态的机器或程序,包含状态节点和状态之间的转换边。FSM 结构类似于有向图,状态之间的转换由输入控制。 - 应用示例(验证输入字符串)
假设输入字符串规则为:第一个和最后一个字符之间可以有多个字母(a...y
),输入字符x
可以使A
状态转换为B
状态;输入非z
字母时B
状态保持;输入z
时,B
状态转换为C
状态。若输入流结束时未处于C
状态,则生成错误。
汇编实现:
; 假设初始状态为 A
mov state, A; 遍历输入字符
check_input:
cmp char, 'x' ; 检查字符是否为 'x'
je A_to_B ; 如果是 'x',从 A 状态转换到 B 状态
cmp char, 'z' ; 检查字符是否为 'z'
je B_to_C ; 如果是 'z',从 B 状态转换到 C 状态
jmp check_inputA_to_B:
mov state, B
jmp check_inputB_to_C:
mov state, C
jmp check_input; 如果最终不在 C 状态,则报错
cmp state, C
jne error