计算机编程基础与实践全解析
1. 基础概念
1.1 汇编语言基础
- 汇编器与链接器 :汇编器将汇编语言的源代码程序转换为机器语言,而链接器则把汇编器生成的各个文件组合成一个可执行程序。
- 学习优势 :汇编语言有助于了解应用程序如何通过中断处理程序、系统调用和公共内存区域与操作系统进行通信,也有助于理解操作系统如何加载和执行应用程序。
- 语句关系 :在一对多的关系中,一条汇编语句会扩展为多条汇编语言或机器指令。
- 可移植性 :一种源程序能在多种计算机系统上编译和运行的语言被称为具有可移植性,但汇编语言通常基于特定的处理器家族或计算机,不具备广泛的可移植性。
- 应用场景 :嵌入式系统应用如汽车燃油和点火系统、空调控制系统等;设备驱动程序可将通用操作系统命令转换为硬件细节的特定引用;适合汇编语言的应用还包括需要直接访问硬件的计算机游戏。
-
代码示例
:对于表达式
X = (Y * 4) + 3,代码如下:
mov eax,Y ; move Y to EAX
mov ebx,4 ; move 4 to EBX
imul ebx ; EAX = EAX * EBX
add eax,3 ; add 3 to EAX
mov X,eax ; move EAX to X
1.2 虚拟机概念
- 计算机层次结构 :计算机是分层构建的,每一层代表从高级指令集到低级指令集的转换层。
- 机器语言特点 :机器语言极其详细且纯粹由数字组成,人类难以理解。
- 程序转换与执行 :一个完整的 LI 程序由专门为此设计的 LO 程序转换为 LO 程序,然后生成的 LO 程序直接在计算机硬件上执行。
- 特定模式 :IA - 32 的虚拟 - 86 操作模式模拟了原始 IBM - PC 中使用的 Intel 8086/8088 处理器的架构;Java 字节码是一种低级语言,在运行时由 Java 虚拟机(JVM)快速执行。
- 层次结构 :包括数字逻辑、微架构、指令集架构、操作系统、汇编语言和高级语言。
1.3 数据表示
- 重要位 :最低有效位是位 0,最高有效位是编号最高的位。
-
数值转换
:给出了多种数值在不同进制下的表示,如十进制、二进制、十六进制等。
| 类型 | 示例 1 | 示例 2 | 示例 3 |
| — | — | — | — |
| 十进制 | 248 | 202 | 240 |
| 二进制 | 00010001 | 101000000 | 00011110 |
| 十六进制 | CF57 | 5CAD | 93EB |
1.4 布尔运算
-
逻辑表达式
:如
(NOT X) OR Y和X AND Y。 -
真值表
:给出了不同逻辑运算的真值表,例如:
| A | B | A ∨ B | ¬(A ∨ B) |
| — | — | — | — |
| F | F | F | T |
| F | T | T | F |
| T | F | T | F |
| T | T | T | F |
2. IA - 32 处理器架构
2.1 通用概念
- 处理器组件 :由控制单元、算术逻辑单元和时钟组成。
- 总线类型 :包括数据总线、地址总线和控制总线。
- 内存与寄存器 :常规内存位于 CPU 外部,对访问请求的响应较慢;寄存器是硬连线在 CPU 内部的。
- 指令执行步骤 :包括取指、解码和执行。
- 操作数处理 :涉及获取和存储内存操作数。
- 并行执行 :通过并行执行处理器阶段,实现机器指令的重叠执行。
- 任务执行 :CPU 通过快速在不同程序之间切换来执行多个任务,给人所有程序同时执行的错觉,操作系统调度器决定每个任务的执行时间并进行任务切换。
2.2 IA - 32 处理器架构细节
- 操作模式 :包括实地址模式、保护模式和系统管理模式。
- 寄存器 :有通用寄存器如 EAX、EBX 等,以及段寄存器 CS、DS 等;ECX 可作为循环计数器;EBP 有特定用途;常见的标志位有进位、符号、零和溢出标志等。
- 浮点单元 :浮点单元(FPU)有 80 位;不同处理器如 Intel 80386、Pentium 等在架构发展中具有重要意义。
- 指令集类型 :CISC 表示复杂指令集,包含大量指令,部分可执行高级语言典型的复杂操作;RISC 表示精简指令集,由一组简单的原子指令组成,可组合成更复杂的操作。
2.3 IA - 32 内存管理
- 内存大小 :支持 4GB(0 到 FFFFFFFFh)的内存,早期有 1MB(0 到 FFFFFh)的内存范围。
- 地址类型 :有线性(绝对)地址;涉及段寄存器如 SS 寄存器,以及局部描述符表和全局描述符表。
- 内存使用情况 :所有加载到内存中的程序总大小可能超过计算机安装的物理内存量。
- 地址示例 :如 0640:0100 和 0630:0200 这两个段 - 偏移地址指向相同的线性地址。
2.4 IA - 32 微型计算机组件
- 内存类型 :SRAM 即静态随机存取存储器,用于 CPU 高速缓存;Pentium 处理器有其特定的应用。
- 中断控制器 :8259 是中断控制器芯片,用于调度硬件中断并中断 CPU。
- 视频内存 :视频内存位于视频板或主板的特殊内存区域。
- 显示原理 :电子束照亮屏幕上的磷光点(像素),水平回扫指电子枪在每行之间关闭的时间段,垂直回扫指绘制完最后一行后电子枪关闭并回到屏幕左上角的过程。
- 其他组件 :还包括动态随机存取存储器(DRAM)、静态随机存取存储器(SRAM)、视频随机存取存储器(VRAM)和互补金属氧化物半导体随机存取存储器(CMOS RAM);USB 接口可查询设备信息并暂停设备电源,这是串行和并行端口所不具备的能力。
2.5 输入 - 输出系统
- 层次结构 :包括应用程序级别、BIOS 级别,BIOS 功能直接与系统硬件通信,且独立于操作系统。
- 应用场景 :游戏程序常尝试利用专业声卡的最新功能,但 Windows - NT、2000 和 XP 会阻止应用程序直接访问系统硬件;同一 BIOS 可用于不同操作系统。
3. 汇编语言基础
3.1 基本元素
- 常量后缀 :有 h、q、o、d、b、r、t、y 等常量后缀。
-
表达式与常量
:如表达式
10 MOD 3,实数常量+3.5E - 02;字符串常量可使用单引号或双引号。 - 指令与注释 :指令包括直接指令;注释可以是多行的,如:
Comment
1
This is a comment
This is also a comment
- 语句结构 :由标签、助记符、操作数和注释组成。
3.2 示例:添加三个整数
-
指令作用
:
INCLUDE指令从I,-vine32.inc文本文件中复制必要的定义和设置信息;.CODE指令标记代码段的开始;程序包含代码段、数据段和堆栈段。 -
过程调用
:通过调用
DumpRegs过程可查看寄存器状态;exit语句用于程序退出;PROC和ENDP指令分别标记过程的开始和结束;END指令标记程序汇编的最后一行,旁边的标签标识程序的入口点;PROTO用于声明当前程序调用的过程名称。
3.3 汇编、链接和运行程序
- 文件类型 :汇编过程会生成目标(.OBJ)和列表(.LST)文件;链接后生成可执行(.EXE)和映射(MAP)文件。
-
选项参数
:如
/F1选项、/Zi选项;/SUBSYSTEM:CONSOLE告诉链接器生成 Win32 控制台应用程序。 -
特殊设置
:
ENTRY可设置程序的起始地址。
3.4 定义数据
-
变量声明
:可声明不同类型的变量,如
SWORD、BYTE、SBYTE、QWORD、SDWORD等,示例如下:
var1 SWORD?
var2 BYTE?
var3 SBYTE?
var4 QWORD?
var5 SDWORD - 2147483648
-
数组声明
:如
wArray WORD 10,20,30,dArray DWORD 50 DUP(?)等。
3.5 符号常量
-
常量定义
:可定义符号常量,如
BACKSPACE = 08h,SecondsinDay = 24 * 60 * 60等;还可使用TEXTEQU进行文本替换,示例如下:
PROCEDURE TEXTEQU <PROC>
Sample TEXTEQU <"This is a string">
MyString BYTE Sample
4. 数据传输、寻址和算术
4.1 数据传输指令
- 操作数类型 :包括寄存器、立即数和内存操作数。
- 指令有效性 :判断指令是否有效,例如:
(a) not valid (b) valid (c) not valid (d) not valid
(e) not valid (f) not valid (g) valid (h) not valid
-
数据传输示例
:给出了不同情况下的数据传输结果,如
(a) FCh (b) 01h等。
4.2 加法和减法
-
指令操作
:如
inc val2,sub eax,val3等;还给出了设置标志位的示例,如CF = 0, SF = 1等。 - 代码示例 :
mov ax,val4
sub val2,ax
- 特殊情况 :讨论了一些特殊情况,如设置进位和溢出标志、设置零标志以指示无符号溢出等。
4.3 数据相关运算符和指令
-
指令判断
:判断一些指令的真假,如
False、True等。 - 数据指令示例 :
data
ALIGN 2
myBytes BYTE 10h, 20h, 30h, 40h
-
操作示例
:如
mov dx, WORD PTR myBytes等。
4.4 间接寻址
- 寻址判断 :判断间接寻址相关指令的真假。
-
数据示例
:给出了不同情况下的间接寻址数据结果,如
(a) 10h (b) 40h (c) 003Bh (d) 3等。
4.5 JMP 和 LOOP 指令
-
指令判断
:判断指令的真假,如
True、False等。 -
循环次数
:
LOOP指令的循环次数,如4,294,967,296 次。 -
特殊情况处理
:对于一些特殊的循环情况,如嵌套循环,给出了处理方法,即在标签 LI 处插入
push ecx,在第二个LOOP指令前插入pop ecx。
5. 过程
5.1 引言
此部分无复习问题。
5.2 链接到外部库
- 库文件性质 :外部库文件包含目标代码。
- 代码示例 :
MyProc PROTO
call MyProc
-
相关库
:涉及
Irvine32.lib和Kernel32.lib,Kernel32.dll是 MS - Windows 操作系统的基础动态链接库。
5.3 书籍链接库
-
常用过程
:如
RandomRange过程、WaitMsg过程等;通过INCLUDE Irvine32.inc包含必要的定义;库中包含过程原型和常量定义。 - 代码示例 :
mov eax,700
call Delay
-
参数说明
:
ESI包含数据的起始地址,ECX包含数据单元的数量,EBX包含数据单元的大小(字节、字或双字);EDX包含字节数组的偏移量,ECX包含要读取的最大字符数。
5.4 堆栈操作
-
堆栈寄存器
:涉及
SS和ESP寄存器;运行时堆栈由 CPU 直接管理,遵循后进先出(LIFO)原则。 -
操作指令
:如
PUSHAD、PUSHFD、POPFD等;ESP在压栈操作时会递减 4;NASM的方法允许程序员指定要压栈的寄存器,而PUSHAD则没有这种灵活性。 -
等效指令
:
PUSH EAX等效于:
sub esp,4
mov [esp],eax
5.5 定义和使用过程
- 过程判断 :判断一些关于过程的陈述的真假。
-
参数说明
:
Receives表示过程调用时的输入参数,Returns表示过程返回时产生的值。 -
代码修改
:对于一些代码,如
add eax,[esi]需修改为add ax,[esi],add esi,4需修改为add esi,2。
5.6 程序设计使用过程
- 设计方法 :采用功能分解或自顶向下的设计方法。
-
常用过程
:如
Clrscr、WriteString、Readint和Writeint等;存根程序包含所有重要过程,但过程可能为空或接近空。 -
代码修改
:对于一些代码,如
mov [esi],eax需修改为mov [esi].ax,add esi,4需修改为add esi,2。
graph TD;
A[PromptForIntegers] --> B[pushad];
B --> C[edx = addr(prompt1)];
C --> D[WriteString];
D --> E[ReadInt];
E --> F[Crlf];
F --> G[[esi] = eax];
G --> H[add esi,4];
H --> I{CX>0?};
I -- 是 --> H;
I -- 否 --> J[popad];
6. 条件处理
6.1 引言
此部分无复习问题。
6.2 布尔和比较指令
-
运算结果
:给出了一些布尔运算和比较指令的结果,如
(a) 00101101 (b) 01001000 (c) 01101111 (d) 10100011等。 - 代码示例 :
and ax,00FFh
or ax,0FF00h
xor eax,0FFFFFFFFh
6.3 条件循环
-
循环指令
:如
JA、JNBE、JAE等;JECXZ用于判断ECX是否为零。 -
比较示例
:比较不同数值,判断是否满足条件,如
JB和JL分别用于无符号和有符号操作数的比较。 - 代码示例 :
cmp dx,cx
jbe L1
6.4 条件循环指令
- 指令判断 :判断指令的真假。
- 代码示例 :
.data
array SWORD 3, 5, 14, -3, -6, -1, -10, 10, 30, 40, 4
sentinel SWORD 0
.code
main PROC
mov esi,OFFSET array
mov ecx,LENGTHOF array
next:
test WORD PTR [esi],8000h ; test sign bit
pushfd ; push flags on stack
add esi,TYPE array
popfd ; pop flags from stack
loopa next ; continue loop while ZF = 1
jz quit ; none found
sub esi,TYPE array ; ESI points to value
-
潜在问题
:如果未找到匹配值,
ESI可能指向数组末尾之外,可能导致数据损坏。
6.5 条件结构
- 代码示例 :给出了不同条件结构的代码示例,如:
cmp bx,cx
jna next
X = 1
next:
-
自动调整优势
:未来对表的更改可能会改变
NumberOfEntries的值,使用汇编器计算的值可以自动调整,避免手动更新常量可能出现的遗忘问题。
6.6 应用:有限状态机
- 基本概念 :有限状态机用有向图表示,节点表示状态,边表示状态之间的转换,由输入引起。
- 状态示例 :如状态 C;识别实数(无指数)的有限状态机示例:
graph LR;
A[start] --> B[digit];
B --> C[digit];
C --> D[digit];
- 限制情况 :提出的有限状态机不允许有符号整数仅由正负号组成。
6.7 决策指令
此部分无复习问题。
7. 整数算术
7.1 引言
此部分无复习问题。
7.2 移位和旋转指令
-
指令类型
:包括
ROL、RCR、SAR、RCL等。 - 代码示例 :
shr al,1 ; shift AL into Carry flag
inc next
Carry flag set?
or al,80h ; yes: set highest bit
next:
no: do nothing
-
运算结果
:给出了一些移位和旋转操作的结果,如
(a) 6Ah (b) EAh (c) FDh (d) A9h等。
7.3 移位和旋转应用
- 字节处理 :对于字节数组,从高位字节开始处理,如:
byteArray BYTE B1h, 20h, 33h
.code
shr byteArray + 2,1
rcr byteArray + 1,1
rcr byteArray,1
- 字处理 :对于字数组,从低位字开始处理,如:
wordArray WORD 810Dh, 0C064h, 93ABh
code
shl wordArray,1
rcl wordArray + 2,1
rcl wordArray + 4,1
- 乘法优化 :对于乘法运算,可进行因式分解优化,如将 24 分解为 16 * 8,21 分解为 16 * 4 + 1。
-
时间处理
:假设时间戳字在
DX寄存器中,可通过shr dx,5和and dl,00111111b提取分钟信息并保存到变量中。
7.4 乘法和除法指令
-
乘积存储
:乘积存储在大小为乘数和被乘数两倍的寄存器中;
IMUL和MUL在处理乘积时有所不同,IMUL进行符号扩展,MUL进行零扩展。 -
标志设置
:
IMUL在乘积的上半部分不是下半部分的符号扩展时设置进位和溢出标志。 - 代码示例 :
mov ax,dividendLow
cwd ; sign - extend dividend
mov bx,divisor
idiv bx
-
表达式实现
:给出了实现无符号和有符号表达式的代码示例,如
val1 = (val2 * val3) / (val4 - 3)和val1 = (val2 / val3) * (val1 + val2)。
7.5 扩展加法和减法
-
指令作用
:
ADC指令将源操作数和进位标志加到目标操作数上,SBB指令从目标操作数中减去源操作数和进位标志。 -
运算结果
:给出了一些运算结果,如
EAX = C0000000h, EDX = 00000010h等。 -
代码优化
:对于一些代码,可使用单个寄存器
ESI进行索引,减少指令数量,如:
mov ecx,8 ; loop counter
mov esi,0 ; use the same index reg
clc ; clear Carry flag
top:
mov al,byte ptr val1[esi] ; get first number
sbb al,byte ptr val2[esi] ; subtract second
mov byte ptr result[esi],al ; store the result
inc esi ; move to next pair
loop top
7.6 ASCII 和非压缩十进制算术
- 代码示例 :
or ax,3030h
and ax,0F0Fh
and ax,0F0Fh ; convert to unpacked
aad
aam
-
输出示例
:给出了一个显示
AX二进制值的过程示例:
out16 PROC
aam
or ax,3030h
push eax
mov al,ah
call WriteChar
pop eax
call WriteChar
ret
out16 ENDP
-
AAA 结果
:执行
AAA后,AX的值会根据特定规则变化,如当AL的低四位大于 9 或辅助进位标志设置时,会进行相应的调整。
7.7 压缩十进制算术
-
标志设置
:当压缩十进制加法的和大于 99 时,
DAA设置进位标志;当较大的压缩十进制整数减去较小的整数时,DAS设置进位标志。 -
示例运算
:如
mov al,56h; add al,92h; DAA后,AL = 48h, CF = 1。 -
调整示例
:假设
AL = 3Dh, AF = 0, CF = 0,DAS会根据规则将AL调整为 37h。
8. 高级过程
8.1 引言
此部分无复习问题。
8.2 栈帧
-
基本概念
:栈帧相关陈述有真假判断,如部分为
True,部分为False。 -
栈帧操作
:栈帧操作包括将
ESP赋值给EBP,然后弹出EBP;RET指令可带整数常量,该常量会在RET弹出返回地址后加到栈指针上。 -
栈帧示例
:栈帧图示例如下:
| 地址 | 内容 |
| — | — |
| [EBP + 16] | 10h |
| [EBP + 12] | 20h |
| [EBP + 8] | 30h |
| [EBP + 4] | (return addr) |
| EBP | <–ESP | -
代码示例
:以下是一个类似
AddTwo过程的AddThree过程示例:
AddThree PROC
push ebp
mov ebp,esp
mov eax,[ebp + 16]; 10h
add eax,[ebp + 12]; 20h
add eax,[ebp + 8] ; 30h
POP ebp
ret 12
AddThree ENDP
-
局部变量声明
:可声明不同类型的局部变量,如
LOCAL pArray:PTR DWORD、LOCAL buffer[20]:BYTE等。 - 调用约定优势 :C 调用约定允许创建具有可变数量参数的过程/函数,最后压入栈的参数可指定已压入栈的参数数量。
8.3 递归
-
终止条件
:递归在
n等于零的时候终止。 - 执行步骤 :每次递归调用完成后,会执行以下指令:
ReturnFact:
mov ebx, [ebp+8]
mul ebx
L2:
pop ebp
ret 4
- 潜在问题 :计算值可能超出无符号双字的范围,导致结果回绕,输出看起来比 12 的阶乘小。
-
栈空间计算
:12 的阶乘需要 156 字节的栈空间,计算方式为
(n + 1)*12。 -
效率问题
:递归的斐波那契算法会低效地使用系统资源,因为对
n的每次调用都会为 1 到n - 1的所有斐波那契数生成函数调用。以下是生成前 20 个值的伪代码:
for(int i = 1; i <= 20; i++)
print( fibonacci(i) );
int fibonacci(int n) {
if( n == 1 )
return 1;
else if( n == 2 )
return 2;
else
return fibonacci(n-1) + fibonacci(n-2);
}
8.4
.MODEL
指令
- 小模式 :一个代码段和一个数据段,所有代码和数据都是近程的,意味着可以仅使用 16 位偏移量访问。
- 平坦模式 :用于保护模式,所有偏移量都是 32 位,代码和数据属于同一分段。
-
选项特点
:
C选项保留标识符的大小写,并在外部名称前加下划线;PASCAL选项将所有标识符转换为大写。
8.5
INVOKE
、
ADDR
、
PROC
和
PROTO
-
指令判断
:对相关指令陈述进行真假判断,如部分为
True,部分为False。 -
过程声明
:可声明过程,如
MultArray PROC ptrl:PTR DWORD, ptr2:PTR DWORD, count:DWORD和MultArray PROTO ptrl:PTR DWORD, ptr2:PTR DWORD, count:DWORD。 - 参数类型 :过程使用输入 - 输出参数,部分参数为输出参数。
8.6 创建多模块程序
-
判断陈述
:对相关陈述进行真假判断,如部分为
True,部分为False。
9. 字符串和数组
9.1 引言
此部分无复习问题。
9.2 字符串原语指令
-
相关寄存器
:涉及
EAX、(E)DI等寄存器;CMPSD用于比较双字;LODSW用于加载字。 -
重复条件
:重复条件如
ZF = 1时重复;REPNE (REPNZ)用于不相等时重复。 -
比较操作
:无论使用何种操作数,
CMPS都会比较ESI和EDI指向的内存内容。 - 匹配结果 :匹配字符后,指针会指向其后面 1 字节的位置。
9.3 选定的字符串过程
-
操作特点
:部分过程的操作特点判断,如部分为
False,部分为True;REPNE (REPNZ)用于不相等时重复。 -
长度计算
:字符串长度可通过
(EDI_final - EDI_initial) - 1计算。 - 特殊检查 :需要检查字符串是否仅包含要修剪的字符。
9.4 二维数组
-
寄存器使用
:可使用任何通用 32 位寄存器;数组访问方式如
[ebx + esi]或array[ebx + esi]。 - 示例代码 :以下是访问二维数组元素的示例代码:
mov esi,2 ; row
mov edi,3 ; column
mov eax,[esi*16 + edi*4]
-
内存模式
:在实地址模式下,
BP指向堆栈段;扁平内存模型中,堆栈和数据使用同一分段。
9.5 搜索和排序整数数组
-
比较次数
:搜索和排序时比较次数逐渐减少,如
n - 1次;时间复杂度示例:T(5000) = 0.5 * 102。 -
二分查找
:二分查找的比较次数为
(log2 n) + 1,如(log2 128) + 1 = 8。 -
代码修改
:修改代码时,可将
JMP L4指令改为JMP L1。
10. 结构和宏
10.1 结构
- 使用场景 :当需要在过程之间传递大量数据时,结构非常必要,一个变量可容纳所有数据。
- 定义示例 :以下是结构定义和使用示例:
MyStruct STRUCT
field1 WORD ?
field2 DWORD 20 DUP(?)
MyStruct ENDS
temp1 MyStruct <>
temp2 MyStruct <0>
temp3 MyStruct <, 20 DUP(0)>
array MyStruct 20 DUP(<>)
-
访问示例
:访问结构成员示例,如
mov ax,array.field1。 -
其他示例
:还给出了使用
SYSTEMTIME结构和Triangle结构的示例。
10.2 宏
-
基本特点
:宏的相关陈述有真假判断,如部分为
False,部分为True;宏可以有参数。 - 代码示例 :以下是不同宏的代码示例:
mPrintChar MACRO char,count
LOCAL temp
.data
temp BYTE count DUP(&char),0
.code
push edx
mov edx,OFFSET temp
call WriteString
pop edx
ENDM
mGenRandom MACRO n
mov eax,n
call RandomRange
ENDM
mPromptInteger MACRO prompt, returnval
mwrite prompt
call ReadInt
mov returnval,eax
ENDM
mWriteAt MACRO X,Y,literal
mGotoxy X,Y
mwrite literal
ENDM
10.3 条件汇编指令
-
指令类型
:包括
IFB用于检查宏参数是否为空,IFIDN用于比较两个文本值是否相同(区分大小写),IFIDNI是其不区分大小写的版本,IFDEF用于判断符号是否已定义,ENDIF用于结束条件判断。 - 代码示例 :以下是条件汇编指令的代码示例:
mWriteLn MACRO text:=<"">
mWrite text
call Crlf
ENDM
mCopyWord MACRO intVal
IF (TYPE intVal) EQ 2
mov ax,intVal
ELSE
ECHO Invalid operand size
ENDIF
ENDM
mCheck MACRO Z
IF Z LT 0
ECHO **** Operand Z is invalid
ENDIF
ENDM
-
特殊运算符
:
&运算符用于解决宏内参数名称的模糊引用,!运算符强制预处理器将预定义运算符视为普通字符,%运算符用于展开文本宏或转换常量表达式为文本表示。
10.4 定义重复块
-
指令类型
:
WHILE指令根据布尔表达式重复语句块,REPEAT指令根据计数器值重复语句块,FOR指令通过遍历符号列表重复语句块,FORC指令通过遍历字符字符串重复语句块。 - 代码示例 :以下是重复块的代码示例:
mRepeat MACRO byteVal,countVal
mov cx,countVal
??0002:
mov ah,2
mov dl,byteval
int 21h
loop??0002
ENDM
-
潜在问题
:在定义链表时,定位计数器的值可能固定在列表的第一个节点,导致
NextPtr字段总是指向第二个节点。
11. MS - Windows 编程
11.1 Win32 控制台编程
-
编译选项
:使用
/SUBSYSTEM:CONSOLE生成 Win32 控制台应用程序。 -
数据类型
:涉及
BOOL = byte、COLORREF = DWORD等数据类型。 -
常用函数
:如
GetStdHandle、ReadConsole、WriteConsole、CreateFile、ReadFile、WriteFile等函数的使用示例:
INVOKE ReadConsole,
stdinHandle,
ADDR buffer,
BufSize - 2,
ADDR bytesRead,
0
INVOKE WriteConsole,
consoleHandle,
ADDR message,
messageSize,
ADDR bytesWritten,
0
INVOKE CreateFile,
ADDR filename,
GENERIC_READ,
DO_NOT_SHARE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0
-
相关结构
:
COORD结构包含屏幕的 X 和 Y 坐标。
11.2 编写图形 Windows 应用程序
-
基本结构
:
POINT结构包含屏幕上点的 X 和 Y 坐标;WNDCLASS结构定义窗口类,每个窗口必须属于一个类,程序需注册主窗口类。 -
函数指针
:
lpfnWndProc是指向应用程序中接收和处理用户触发的事件消息的函数的指针。 -
窗口样式
:窗口样式由多个常量组合而成,如
MAIN_WINDOW_STYLE = WS_VISIBLE + WS_DLGFRAME + WS_CAPTION + WS_BORDER + WS_SYSMENU + WS_MAXIMIZEBOX + WS_MINIMIZEBOX + WS_THICKFRAME。 -
消息框使用
:使用
MessageBox显示消息框,可选择不同的按钮组合和图标常量,如MB_OK、MB_ICONHAND等。 -
WinMain任务 :WinMain执行的任务包括获取当前程序的句柄、加载程序的图标和鼠标光标、注册主窗口类、创建主窗口、显示和更新主窗口、开始消息接收和分发循环。 -
消息处理
:
WinProc过程接收和处理与窗口相关的所有事件消息,处理的消息包括WM_LBUTTONDOWN、WM_CREATE、WM_CLOSE等;ErrorHandler过程在系统报告错误时调用。 - 消息框显示时机 :消息框在应用程序主窗口出现前和关闭前显示。
11.3 动态内存分配
-
基本概念
:涉及动态内存分配;
HeapCreate用于创建堆,示例如下:
HEAP_START = 2000000 ; 2 MB
HEAP_MAX = 400000000 ; 400 MB
.data
hHeap HANDLE ? ; handle to heap
.code
INVOKE HeapCreate,
0,
HEAP_START,
HEAP_MAX
- 操作方法 :分配内存块可通过相关函数,释放内存需传递内存块指针和堆句柄。
11.4 IA - 32 内存管理
- 基本概念 :多任务允许多个程序同时运行,处理器在它们之间分配时间;分段可隔离内存段,允许多个程序同时运行而不相互干扰。
- 地址类型 :段选择器是存储在段寄存器中的 16 位值,逻辑地址由段选择器和 32 位偏移量组成;线性地址是 32 位整数,可能是物理地址(分页禁用时),分页启用时,处理器会将线性地址转换为物理地址。
-
内存表相关
:涉及
LDTR寄存器、GDTR寄存器;每个任务或程序有自己的局部描述符表;线性地址包括页目录项指针、页表项指针和页帧偏移量三个字段。
12. 高级语言接口
12.1 引言
- 命名规则 :语言的命名规则涉及变量和过程的命名规则和特点。
-
内存模型
:包括
Tiny、small、compact、medium、large、huge等内存模型;内存模型决定是近调用还是远调用,近调用仅将返回地址的 16 位偏移量压入栈,远调用将 32 位段/偏移地址压入栈。 -
语言特性
:C 和 C++ 区分大小写,部分语言要求在过程调用中保留
EBP (BP)、ESI (SI)和EDI (DI)的值。
12.2 内联汇编代码
-
基本概念
:内联汇编代码是直接插入高级语言程序中的汇编语言源代码,C++ 中的
inline限定符则是请求编译器将函数体直接插入程序的编译代码中,以避免调用和返回函数的额外执行时间。 - 注释示例 :以下是内联汇编代码注释的示例:
mov esi,buf ; initialize index register
mov esi,buf // initialize index register
mov esi,buf /* initialize index register */
-
潜在问题
:
_fastcall约定可能导致程序错误,因为编译器可能使用通用寄存器作为临时变量;可使用LEA指令;LENGTH运算符返回DUP运算符指定数组的元素数量,SIZE运算符返回TYPE * LENGTH的乘积。
12.3 与 C++ 在保护模式下链接
-
关键字使用
:需要使用
extern和"C"关键字。 -
调用约定差异
:
Irvine32库使用STDCALL,与 C 和 C++ 使用的 C 调用约定在函数调用后清理栈的方式不同。 -
浮点处理
:浮点值通常在函数返回前压入处理器的浮点栈;短整数在
AX寄存器中返回。 -
函数声明
:
printf函数声明示例:printf PROTO C, pString:PTR BYTE, args:VARARG。 -
参数顺序
:参数
X最后压入栈;使用关键字可防止 C++ 编译器对外部过程名称进行修饰,避免名称不匹配问题;操作数组时,数组下标和指针的效率相近。
12.4 与 C/C++ 在实地址模式下链接
-
保存值要求
:Borland C++ 调用的汇编过程必须保留
BP、DS、SS、SI、DI和方向标志的值。 -
数据类型大小
:
INT = 2、enum = 1、float = 4、double = 8。 - 代码示例 :以下是实地址模式下的代码示例:
mov eax,[ebp + 6]
-
特殊操作
:
rot eax,8语句可避免生成小随机数序列时出现重复模式。
13. 16 位 MS - DOS 编程
13.1 MS - DOS 和 IBM - PC
-
内存范围
:内存范围可达
9FFFFh;中断向量表位于特定位置;00400h有特殊用途;BIOS 有重要作用。 -
输出重定向
:程序输出可重定向到默认打印机,如
myProg > prn;LPT1是常用的打印机端口。 -
中断服务
:中断服务例程为应用程序提供基本服务并处理硬件事件;处理中断时需将标志压入栈,处理完成后执行
IRET指令;常见的中断号如10h、1Ah、21h * 4 = 0084h。
13.2 MS - DOS 函数调用(INT 21h)
-
函数覆盖
:
INT 21h覆盖了所有功能。 -
常用函数
:包括
4Ch用于程序退出,2和6用于写入单个字符,9用于显示字符串,40h用于文件写入,1和6用于读取字符,37h用于文件搜索,2Ah和2Bh用于获取和设置系统日期和时间。
13.3 标准 MS - DOS 文件 I/O 服务
-
设备句柄
:设备句柄包括
0 = 键盘(标准输入)、1 = 控制台(标准输出)、2 = 错误输出、3 = 辅助设备(异步)、4 = 打印机。 - 操作示例 :以下是打开文件、读取文件和移动文件指针的操作示例:
; 打开现有文件进行输入
.data
infile BYTE "myfile.txt",0
inHandle WORD ?
.code
mov ax,716Ch ; extended create or open
mov bx,0 ; mode = read-only
mov cx,0 ; normal attribute
mov dx,1 ; action: open
mov si,OFFSET infile
int 21h
jc quit ; quit if error
mov inHandle,ax
; 从文件读取二进制数组
mov ax,3Fh
mov bx,open file handle
mov cx,maximum bytes to read
mov ds:dx,address of input buffer
int 21h
; 移动文件指针
mov ah,42h
mov al,0 ; method: offset from beginning
mov cx,0
mov dx,50 ; offsetLo
int 21h
-
结束判断
:调用
INT 21h后,比较AX的返回值和调用前CX的值,若AX较小,则表示到达文件末尾。
13.4 读写磁盘扇区(7305h)
- 操作模式 :该函数在实地址模式下运行。
-
参数说明
:参数包括
AX: 7305h、DS:BX: 0151(10) 结构变量的段/偏移量、CX: 0FFFFh、DL: 驱动器号(0 = 默认,1 = A,2 = B,3 = C 等)、SI: 读写标志。 -
显示特点
:
INT 10h可显示特殊 ASCII 图形字符而不解释为控制码;若7305h函数无法读取请求的扇区,进位标志会被设置,程序会显示错误消息。
13.5 系统级文件函数
-
函数类型
:包括
7303h等函数。
14. 磁盘基础知识
14.1 磁盘存储系统
-
基本特性
:部分特性判断,如部分为
True,部分为False;磁盘有柱面,扇区大小通常为 512 字节。 - 访问优化 :相邻柱面可加快访问速度,避免磁头跳跃浪费时间和增加错误概率;磁盘分区表和引导扇区用于定位单个分区的引导扇区并加载操作系统;通常有一个系统分区。
14.2 文件系统
-
特性判断
:部分文件系统特性判断,如部分为
True,部分为False;FAT32 和 NTFS 是常见的文件系统,NTFS 有更多优势;文件系统包括引导记录、文件分配表、根目录和数据区域;文件大小和簇使用情况会影响磁盘空间的使用效率。
14.3 磁盘目录
-
基本概念
:部分概念判断,如部分为
True,部分为False;根目录有特殊名称;目录项包含文件名、扩展名、属性、时间戳、起始簇号和文件大小等信息;时间戳的位分配有特定规则;长文件名可能需要多个目录项;文件分配表通过链接指示文件的簇顺序。
14.4 读写磁盘扇区(7305h)
-
操作判断
:部分操作判断,如部分为
True,部分为False;该函数在实地址模式下运行,参数如上述所述;INT 10h显示特殊字符;若读取失败,进位标志会被设置并显示错误消息。
14.5 系统级文件函数
-
函数类型
:包括
7303h、39h(创建子目录)、3Bh(设置当前目录)、7143h(获取和设置文件属性)等函数。
15. BIOS 级编程
15.1 引言
此部分无复习问题。
15.2 键盘输入(INT 16h)
-
最佳选择
:
INT 16h是获取键盘输入的最佳选择;键盘输入先存储在0040:001E位置的缓冲区中;INT 9h读取键盘输入端口,获取扫描码并生成 ASCII 码,然后将两者插入缓冲区。 -
函数使用
:使用
05h、10h、11h、12h等函数;可通过test al,100h判断Ctrl键是否按下;可添加更多CMP和JE指令检查其他按键,如ESC、F1和Home键。
15.3 视频编程(INT 10h)
-
编程层次
:包括 MS - DOS 级、BIOS 级和直接视频级;在 MS - Windows 中,可通过创建快捷方式或使用
Alt - Enter切换到全屏模式;模式3是常见的彩色 80 X 25 模式。 -
显示原理
:屏幕上每个字符由 ASCII 码和属性(2 字节)表示;颜色由红、绿、蓝和强度组成,背景和前景颜色由不同位表示;使用
02h、06h、09h、01h、00h等函数进行视频操作;可通过特定方法隐藏光标;滚动屏幕和显示字符有相应的参数设置。
15.4 绘图图形(INT 10h)
-
函数参数
:
AH = 0Ch用于绘制像素,参数包括像素值、视频页面、X 坐标和 Y 坐标;绘图速度较慢。 - 模式设置 :以下是设置视频模式的示例:
mov ah,0 ; set video mode
mov al,11h ; to mode 11h
int 10h ; call the BIOS
-
坐标转换
:图形坐标可根据公式
sx = (sOrigX + X)进行转换。
15.5 内存映射图形
-
基本概念
:部分概念判断,如部分为
False,部分为True;模式13h将每个像素的整数值映射到调色板;像素的颜色索引指定调色板中使用的颜色;调色板中的每个条目由红、绿、蓝三个整数值(0 到 63)组成;可通过以下代码设置屏幕背景颜色:
mov dx,3c8h
mov al,0 ; index 0 (background color)
out dx,al
mov dx,3c9h
mov al,63 ; red
out dx,al
mov al,63 ; green
out dx,al
15.6 鼠标编程
-
函数使用
:使用
0、1、2、3、4、5、6、7、8等函数进行鼠标操作,以下是部分函数的代码示例:
; 重置鼠标
mov ax,0
int 33h
; 获取鼠标位置和状态
mov ax,3
int 33h
mov mouseX,cx
mov mouseY,dx
; 设置鼠标位置
mov ax,4
mov cx,100 ; X-value
mov dx,400 ; Y-value
int 33h
; 获取按钮按下信息
mov ax,5
mov bx,0 ; button ID for left button
int 33h
test ax,1 ; left button currently down?
jne Button1 ; yes: jump to label
; 获取按钮释放信息
mov ax,6
mov bx,1 ; button ID
int 33h
test ax,2 ; right button released?
jz skip ; no - skip
mov mouseX,cx
mov mouseY,dx
skip:
- 坐标计算 :假设字符单元格为 8 像素 X 8 像素,可根据坐标计算鼠标在单元格中的位置;鼠标由 Douglas Engelbart 在 1963 年发明。
16. 专家级 MS - DOS 编程
16.1 引言
此部分无复习问题。
16.2 定义段
-
段声明
:
SEGMENT指令声明段的开始;SEG指令返回数据或代码标签的段地址;ASSUME指令帮助汇编器在汇编时计算标签和变量的偏移量。 -
段属性
:段属性包括
BYTE、WORD、DWORD、PARA、PAGE等类型;组合类型包括PRIVATE、PUBLIC、MEMORY、STACK、COMMON、AT等,用于告诉链接器如何组合同名段;可使用AT组合类型定义特定地址的段;段的类类型可用于组合不同名称但类类型相同的段。 - 代码示例 :以下是访问段内存的代码示例:
mov al,es:[di]
16.3 运行时程序结构
-
执行流程
:命令处理器先检查当前目录中是否有
.COM扩展名的文件,若有则执行,否则按后续步骤处理;应用程序通常加载到最低 640K 内存,执行完后自动卸载;程序段前缀有特定的偏移量。 -
COM 程序特点
:COM 程序是单段 MS - DOS 程序,存储为
.COM文件时是内存加载时的二进制映像;使用Tiny内存模型;效率不高,因为最小的 COM 程序也使用整个 64K 内存段;所有段寄存器初始化为程序内的偏移量零,程序加载到内存中其他程序之后的第一个可用段位置。 -
指令作用
:
ORG指令为后续标签或指令分配特定偏移量;DS和ES指向程序段前缀区域;MS - DOS 通常在程序加载时自动分配所有可用内存,除非程序的.EXE头文件限制最大内存分配大小;EXEMOD程序可显示程序内存使用统计信息并修改.EXE头文件的设置;可通过运行EXEMOD程序查看重定位项数量。
16.4 中断处理
-
中断响应
:中断发生时,程序可能显示 “Abort, retry, or ignore?” 消息并终止当前程序;中断向量是指向中断处理程序的 32 位段/偏移地址,位于
0000:0040h;8259可编程中断控制器芯片用于调度硬件中断。 -
标志操作
:使用
CLI指令清除中断标志,STI指令设置中断标志;IRQ 0优先级最高;键盘中断(IRQ 1)优先级高于磁盘驱动器中断(IRQ 14);中断处理程序结束时执行IRET指令返回控制权;使用25h和35h函数设置和获取中断向量。 -
特殊程序
:中断处理程序可能在应用程序启动时加载,结束时卸载;内存驻留程序即使安装它的程序结束后仍保留在内存中;终止并驻留(TSR)程序通过调用
INT 21h函数31h部分保留在内存中;可通过重启计算机或使用特殊实用程序移除 TSR 程序;中断处理程序可通过JMP指令跳转到先前存储在中断向量中的地址;Ctrl + Alt + Right shift + Del可触发特定操作。
17. 浮点处理和指令编码
17.1 浮点二进制表示
- 表示限制 :某些值(如 - 127 的倒数)会导致溢出,添加 + 128 到指数偏置会产生负值;尾数部分为 52 位,指数部分为 8 位。
-
数值转换
:将十进制数转换为二进制浮点表示,如
1101.01101 = 13/1 + 1/4 + 1/8 + 1/32,0.2会产生无限循环的二进制位模式;特殊值包括安静 NaN 和信号 NaN;以下是一些数值的二进制浮点表示示例:
+1110.011 = 1.110011 x 2^3,编码为 0 01111100 11001100000000000000000
+ 10.75 = + 1010.11 = +1.01011 X 2^3,编码为 0 10000010 01011000000000000000000
-76.0625 = -01001100.0001 = -1.0011000001X2^6,编码为 1 10000101 00110000010000000000000
17.2 浮点单元
-
相关操作
:
fld st(0)用于加载栈顶元素;RO是舍入控制位;浮点单元的寄存器包括操作码、控制、状态、标签字、最后指令指针和最后数据指针;支持二进制编码十进制;REAL 10为 80 位;FCHS用于改变符号;FISUB用于将源操作数从整数转换为浮点数;FCOM或FCOMP用于比较浮点数。 - 代码示例 :以下是获取浮点状态字和标志的代码示例:
fnstsw ax
lahf
-
舍入规则
:浮点数舍入到最接近的偶数,如
1.010101101舍入为1.010101110,-1.010101101舍入为-1.010101110。 -
计算示例
:以下是计算表达式
P = (N * (-N) + B)的汇编代码示例:
.data
B REAL8 7.8
M REAL8 3.6
N REAL8 7.1
P REAL8 ?
.code
fld N
fchs
fld N
fadd B
fmul
fst P
17.3 英特尔指令编码
-
编码示例
:给出了不同指令的机器语言编码示例,如
(a) 8E (b) 8B (c) 8A (d) 8A (e) A2 (f) A3等。 -
机器语言字节
:以下是一些指令的机器语言字节示例:
```plaintext
a. 8ED8
b. A00000
c. 8B0E0100
d. BA0000
超级会员免费看

被折叠的 条评论
为什么被折叠?



