幻灯片 1 - 华北理工大学教务处

Download Report

Transcript 幻灯片 1 - 华北理工大学教务处

《汇编语言程序设计》
课程研讨
清华大学计算机系
毛希平
1.课程定位
课程建设的基本情况
课程定位与教学目标
课程内容与教学方式
课程重点与难点解析
实验设置与考核方式
个人体会与大家交流
汇编
语言
982年计算机系在国内率先开设。
课程建设的基本情况
• PDP-11 汇编语言程序设计(82年)
• IBM PC 汇编语言程序设计(87年)
• 80x86 汇编语言程序设计
汇编
语言
课程定位与教学目标
课程定位:计算机专业基础课
专业课程的先导课
汇编
语言
在学习汇编之前:
以下高级语言中的问题你可能不能给出(正确的)答案:
汇编
语言

程序是怎么开始和结束的?

指令是怎么执行的?

代码和数据是如何分布的?

全局变量和局部变量是怎样存储的?

循环和分支结构是怎样实现的?

子程序的调用和返回是如何进行的?参数是怎么传递的?

……
更微观的问题还有:
 for、while、do…while循环的实现效率有什么不同吗?
条件分支if…else与switch…case呢?
 乘法和除法是怎么做的?
 溢出是怎么回事?堆栈是什么?
 带符号整数(int)和无符号整数(unsigned int)在运
算上有什么差别?
 C/C++中的指针是什么?
 ……
汇编
语言
学生关于汇编语言的疑问:
什么是汇编语言(Assembly Language)?
汇编语言与高级语言的关系?
汇编语言的地位?重要性?
汇编语言的应用?
汇编
语言
C/C++源程序
汇编
语言
反汇编代码
汇编
语言
摘自CMU教学计划
汇编语言是完整理解计算机系统的最佳起点和最有效途径。
高级语言程序
理解
汇编语言程序
感知
操作系统
硬
件
计算机系统
汇编
语言
教学目标:
• 学习一种编程语言,使学生获得在计算机
低层编程的经验;
• 建立计算机系统的整体概念 ( 机器与程序
时间与空间 ),为后续课程打好基础;
• 培养分析问题和实际解决问题的能力。
汇编
语言
课程内容与教学方式
汇编
语言
注重基础、实用
体现发展、更新
教材:
IBM-PC 汇编语言程序设计 (第2版),
沈美明 温冬婵 清华大学出版社
系列教材:
IBM-PC 汇编语言程序设计
IBM-PC 汇编语言程序设计实验教程
每学期80学时:
原来64(课堂教学)+16(上机) →目前48(课堂教学)+32 (上机)
汇编
语言
第一章 基础知识
1.1
1.2
1.3
1.4
进位计数制与不同基数的数之间的转换
二进制数和十六进制数运算
计算机中数和字符的表示
几种基本的逻辑运算
第二章 80x86计算机组织
2.1
2.2
2.3
2.4
汇编
语言
4学时
4学时
计算机系统构成
80x86微处理器(CPU)
存储器和外部设备
基本操作模式(实模式,保护模式,V86模式)
第三章 指令系统和寻址方式
12学时
3.1 80x86的寻址方式
3.2 机器语言指令概况
3.3 80x86指令系统
第四章 汇编语言程序格式
4.1
4.2
4.3
4.4
汇编程序功能
伪操作
汇编语言程序格式
汇编语言程序的上机过程
第五章 循环与分支程序
5.1 循环程序设计
5.2 分支程序设计
汇编
语言
4学时
4学时
第六章 子程序结构
6学时
6.1 子程序的设计方法
6.2 嵌套与递归子程序
6.3 子程序举例
第七章 高级汇编语言技术
7.1 宏汇编
7.2 重复汇编
7.3 条件汇编
汇编
语言
4学时
第八章 I/O程序设计
8.1
8.2
8.3
8.4
I/O设备的数据传送方式
程序直接控制I/O方式
中断方式
保护模式下的中断处理
第九章 BIOS和DOS中断
9.1
9.2
9.3
9.4
汇编
语言
4学时
2学时
键盘I/O
显示器I/O
打印机I/O
串行通信口I/O
图形与发声系统的程序设计
磁盘文件存取技术
自学
自学
第十章 模块化程序设计
10.1
10.2
10.3
10.4
汇编
语言
4学时
汇编程序概述
连接程序及连接对程序设计的要求
汇编语言程序与高级语言程序的连接
模块化程序设计概述
教学方式:
• 体现研究型教学理念
创新、新颖、生动、交互式、多样化
• 注重系统性和完整性,要突出重点
• 有意识地引入后续课程中的问题,为学生做
理论和技术上的准备,也提高了学习兴趣。
• 通过自学培养学生学习的主动性
• 强化实验环节,重视实验指导
• 多元化考核保证教学质量
汇编
语言
课程重点与难点解析
汇编课对于学生来说是一门全新的课程,尽管在此之
前他们大多学过一门或两门高级语言,有一定的编程经历
和程序设计能力。
汇编这种低级语言比较独特,从形式到结构与高级语
言有很大不同,它不像高级语言那样容易“入门”,学生
在学习过程中尤其在课程的前半段充满了疑惑,几乎每一
章都有难点,这就要求我们在教学方法上狠下功夫。
学生遇到的难点主要分两种:一是基本概念方面的,
对这些概念和基础知识正确而清晰的理解非常重要;二是
应用和编程方面的(主要体现在程序格式或结构上)。
汇编
语言
第一章 基础知识
熟悉并习惯二进制、特别是十六进制数
进制之间的转换
算术运算和逻辑运算
有符号数和无符号数
机器数的补码表示、补码的加减法、溢出
字符和汉字的表示 ASCII码表
汇编
语言
关于溢出:
汇编
语言
第二章 80x86计算机组织
寄存器的名称和用途(通用 / 专用)
内存单元的地址和内容
寄存器与存储器的比较
实模式下段的概念
物理地址和逻辑地址(段地址和偏移地址)
实模式与保护模式的含义
汇编
语言
80x86的寄存器结构:
EAX
EBX
ECX
EDX
ESP
EBP
ESI
EDI
AH
BH
CH
DH
AX
BX
CX
DX
SP
BP
SI
DI
AL
BL
CL
DL
8086 /
8088 /
80286
EIP
EFLAGS
IP
FLAGS
寄
存
80x86的程序可见寄存器组
通用寄存器
专用寄存器
段寄存器
汇编
语言
CS
DS
SS
ES
FS
GS
器
8086/8088
OF DF IF TF SF ZF
AF
PF
80x86的标志寄存器
CF
80286
NT IOPL OF DF IF TF SF ZF
AF
PF
CF
80386
VM RF
NT IOPL OF DF IF TF SF ZF
AF
PF
CF
80486
AC VM RF
NT IOPL OF DF IF TF SF ZF
AF
PF
CF
Pentium
ID VIP VIF AC VM RF
31 30
汇编
语言
29 28
27 26
25 24
23 22 21
20
19 18 17
16 15
NT IOPL OF DF IF TF SF ZF
14 13
12 11
10
9
8
7
6
AF
5
4
PF
3
2
CF
1
0
汇编
语言
寄
汇编
语言
存
器
存
储
器
在CPU内部
在CPU外部
访问速度快
访问速度慢
容量小,成本高
容量大,成本低
用名字表示
用地址表示
没有地址
地址可用各种方式形成
第三章 指令系统和寻址方式
篇幅大,内容多,需要精心组织
什么是寻址(数据 代码)
各种寻址方式的适用场合、所用寄存器的限制、
扩展后寻址方式(比例因子)的新特征
Offset =
eax
ebx
ecx
edx
esp
ebp
esi
edi
Base
汇编
语言
+
eax
ebx
ecx
edx
esp
ebp
esi
edi
Index
*
1
2
4
8
scale
None
8-bit
+
16-bit
32-bit
displacement
段寄存器的使用规定
访问存储器的方式
汇编
语言
默认的
段寄存器
可跨越的
段寄存器
偏移地址
取指令
CS
无
IP
堆栈操作
SS
无
SP
一般数据访问
DS
CS ES SS
EA
BP 作为基址的寻址
SS
CS DS ES
BP
串操作的源操作数
DS
CS ES SS
SI
串操作的目的操作数
ES
无
DI
指令系统分类:
数据传送指令
重点关注:
算术指令
指令的汇编格式
逻辑指令
指令的基本功能
串处理指令
指令支持的寻址方式
控制转移指令
指令的执行对标志位的影响
处理机控制与杂项操作指令
指令的特殊要求
大量练习,尽早上机
汇编
语言
指令隐含使用寄存器(乘法除法、串处理、IN/OUT等)
一条指令对应多项操作(PUSH/POP/CALL/RET…
串处理的MOVS/STOS/LODS/CMPS指令等)
加、减、求补指令对 CF/OF 的影响
与 REP/REPE/REPNE 配合工作的串处理指令
(1) 如 (CX) = 0 或 ZF = 0 则退出,否则转 (2)
汇编
语言
(2)
(CX) ← (CX) - 1
(3)
执行 CMPS / SCAS
(4)
重复 (1) ~ (3)
循环指令LOOP/LOOPZ/LOOPNZ
执行步骤:
(1) ( CX ) ← ( CX ) - 1
(2) 是否满足测试条件……
汇编
语言
80x86 的指令系统:
(1) 指令集的 32 位扩展
* 所有 16 位指令都可扩展到 32 位
MOV EAX , 1
* 可使用 32 位的存储器寻址方式
MOV EAX , [ EDX ]
(2) 使用方式的扩展
* IMUL:单操作数指令 → 双操作数指令 / 三操作数指令
IMUL REG , SRC
* PUSH:允许使用立即数寻址方式
PUSH
36H
* 移位指令:移位次数可用 8 位立即数 (1~31)
汇编
语言
(3) 新增指令
第四章 汇编语言程序格式
源程序的每条语句可表示为:
[名字]
操作
操作数
标号
指令
寄存器
变量
伪指令
标号
宏指令
变量
[; 注释]
说明程序或语句的功能
常数
表达式
标号/变量:段值、偏移量、类型三种属性
表达式:数字表达式
汇编
语言
地址表达式
实模式编程 保护模式编程(DOS编程 WIN32编程)
完整段定义 简化段定义
完整段定义
data
data
extra
extra
code
segment
…
ends
segment
…
ends
segment
assume cs:code,
; 定义数据段
; 定义附加段
; 定义代码段
ds:data, es:extra
start:
code
汇编
语言
DS 
ES
SS
CS
mov
mov
…
ends
end
ax, data
ds, ax
start
; 段地址  段寄存器
PSP
文
件
头
装
入
模
块
EXE 程序的内存映象图
几种返回形式:
……
code
main
main
code
汇编
语言
segment
proc far
assume ……
push ds
mov
ax, 0
push ax
……
ret
endp
ends
end
main
……
code
main
segment
proc far
assume ……
start:
……
……
mov ax,4c00h
int 21h
main endp
code ends
end start
data
data
stack
stack
code
main
segment
……
ends
segment
dw
tos
ends
segment
proc
assume
带堆栈段的汇编源程序:
100
label
dup (?)
word
far
cs:code, ds:data, ss:stack
start:
main
code
汇编
语言
mov
mov
mov
push
sub
push
mov
mov
……
ret
endp
ends
end
ax,
ss,
sp,
ds
ax,
ax
ax,
ds,
stack
ax
offset
tos
ax
DS 
ES
data
ax
SS
CS
start
PSP
堆栈段的情况:
……
stack
stack
……
……
汇编
语言
segment
dw
100
tos
label
ends
dup (?)
word
mov
mov
mov
ax,
ss,
sp,
stack
ax
offset
push
sub
push
ds
ax,
ax
ax
100字
tos
tos

00C8H sp
data
data
stack
stack
汇编
语言
segment
……
ends
segment
dw
tos
ends
code
segment
……
start:
push
sub
push
mov
mov
……
ret
……
code
ends
end
stack
100
label
ds
ax,
ax
ax,
ds,
ax
data
ax
dup (?)
word
DS 
ES
SS
CS
start
PSP
C/C++中定义的局部变量(数组)在堆栈中的分布:
int main()
{
int ar0[]={0,1,2};
int ar1[]={1,2,3};
int ar2[]={2,3,4};
int *p[]={ar0,ar1,ar2};
……
}
汇编
语言
0012FF50 0012FF74 p
0012FF54 0012FF68
0012FF58 0012FF5C
0012FF5C
2
0012FF60
3
0012FF64
4
0012FF68
1
0012FF6C
2
0012FF70
3
0012FF74
0
0012FF78
1
0012FF7C
2
ar2
ar1
ar0
简化段定义
.model small
.data
……
.code
.startup
……
.exit 0
end
汇编
语言
.model small
.const
……
.data
……
.code
start: mov ax, DGROUP
mov ds, ax
……
mov ax, 4c00h
int 21h
end start
.model small
.data
……
.code
start: mov ax, @data
mov ds, ax
……
mov ax, 4c00h
int 21h
end start
完整段定义和简化段定义的区别:
描述信息 数据和代码的分布不同
data
data
extra
extra
汇编
语言
segment
string1
mass1
mass2
ends
db
db
db
'thamks you'
'match.', 13, 10, '$'
'no match!', 13, 10, '$'
segment
string2
ends
db
'thanks you'
.data
string1
string2
mass1
mass2
汇编
语言
db
db
db
db
'thamks you‘
'thanks you'
'match.', 13, 10, '$'
'no match!', 13, 10, '$‘
数据定义伪操作
与高级语言(数据类型与变量定义)类比 总结 分类
数据类型
字符和字符串
AsciiNULL db
0
szMsg
db
“Hello World!”,13,10,0
szBuffer
db
256 dup(?)
lib_name
BYTE
“\masm32\lib\kernel32.lib”
整数和整数数组
dwFlag
dw
0ffffh
val1
SWORD -32768
; 最小的16位有符号数
val2
BYTE
; 最大的8位无符号数
255
MASM6.0以上的编译器专门提供了无符号数定
义伪指令(BYTE、WORD、DWORD等)和有符号数定义
伪指令(SBYTE、SWORD、SDWORD等)。
例:
array1
SDWORD
1,2,3,4,5,6,7,8,9,10
array2
BYTE
array3
BYTE
array4
SWORD
SWORD
SWORD
SWORD
1,0,0,0
0,1,0,0
0,0,1,0
0,0,0,1
array5
SWORD
1,0,0,0,
0,1,0,0,
0,0,1,0,
0,0,0,1
41h,42h,43h,44h,45h,46h,47h,48h,49h,\
4ah,4bh,4ch,4dh,4eh,4fh,50h,51h,52h,\
53h,54h,55h,56h,57h,58h,59h,5ah
“ABCDEFGHIJKLMNOPQRSTUVWXYZ”
例:
array3
BYTE
“ABCDEFGHIJKLMNOPQRSTUVWXYZ”
……
cld
mov
mov
mov
esi, offset array3
edi, esi
ecx, lengthof array3
again:
lodsb
add
al, 20h
stosb
loop again
……
指针
; 定义目标数据对象
val1
array3
SWORD -32768
BYTE “ABCDEFGHIJKLMNOPQRSTUVWXYZ”
; 定义指针
lp1
lp2
DWORD val1 ;
DWORD array3
保护模式下用DWORD,实模式下用WORD
或者:
lp1
lp2
DWORD offset val1
DWORD offset array3
使用typedef操作符自定义指针类型:
lpSWORD
typedef
PTR SWORD
lpBYTE
typedef
PTR BYTE
lp1
lp2
lpSWORD
lpBYTE
val1
array3
例:
lpBYTE
……
typedef
array3
lp
.data
BYTE “ABCDEFGHIJKLMNOPQRSTUVWXYZ”
lpBYTE
array3
PTR BYTE
.code
……
mov
edi, lp
mov
ecx, lengthof array3
again:
add
add
loop
……
BYTE PTR [edi], 20h
edi, type array3
again
结构
STUDENT
struct
id
szName
age
sex
STUDENT
BYTE
BYTE
BYTE
BYTE
; 定义结构类型STUDENT
“??????????”
18 dup(?)
?
?
;
;
;
;
学号
姓名
年龄
性别
ends
定义变量
.data
stu1 STUDENT
stu2 STUDENT
<"20090001","ZhaoXiaofang",18,"F">
{}
; 初始化
; 未初始化
SYSTEMTIME
struct
wYear
WORD
wMont
WORD
wDayOfWeek
WORD
wDay
WORD
wHour
WORD
wMinute
WORD
wSecond
WORD
wMilliseconds WORD
SYSTEMTIME
; windows.inc
?
?
?
?
?
?
?
?
;
;
;
;
;
;
;
;
年(4位数)
月[1,12]
星期[0,6]
日[1,31]
时[0,23]
分[0,59]
秒[0,59]
毫秒[0,999]
ends
.data
ctime
SYSTEMTIME
<>
GetLocalTime PROTO :DWORD
invoke
GetLocalTime, addr ctime
; 未初始化,存放获取的当前时间
; 带一个结构变量地址参数
; addr用于取变量地址
2009(十六进制07D9)年
8月8日星期六
11时01分18秒906毫秒
联合
CHARTYPE
CHARTYPE
char1
char2
union
UnicodeChar WORD
AsciiChar
BYTE
ends
CHARTYPE
CHARTYPE
IMAGE_SYMBOL struct
union N
ShortName
struct Name1
Short1
Long1
ends
LongName
ends
Value
SectionNumber
Type1
StorageClass
NumberOfAuxSymbols
IMAGE_SYMBOL ends
; 定义联合类型CHARTYPE
?
?
<61h>
<0c3bah>
; Ascii字符“a”
; Unicode字符“好”
dd
dd
; 定义结构类型IMAGE_SYMBOL
; 结构中内嵌联合N
8 dup(?)
; 联合中内嵌结构Name1
?
?
dd
2 dup(?)
dd
dw
dw
db
db
?
?
?
?
?
db
记录
变量定义
变量名:除了字母、数字(不能是首字符)和下划线,还可以使用
@、$和?
全局变量 定义在.data或.data?段中,作用域是整个程序,具
有静态(全局)生存期。
.data
szMsg
db
“Hello
World!”,13,10,0
array
SDWORD
10 dup(?)
局部变量
LOCAL
例如:
LOCAL
LOCAL
LOCAL
LOCAL
变量名1[重复数量][:类型],变量名2[重复数量][:类型]……
str[16]:BYTE
var
ctime:SYSTEMTIME
lp:lpBYTE
全局变量与局部变量的存储特性
全局变量与局部变量的地址获取
mov
eax, offset var1
或者:
lea
eax, var1
invoke
GetMessage, ADDR msg
; var1是全局变量
对局部变量而言,由于保存在堆栈中,它们的地址与esp或ebp
有关,只有在程序运行时才能确定下来。因此不能用offset操作符,
而只能用lea。
汇编
语言
在实模式下使用32bit操作数
目的:在实模式下发挥80386及其后继机型的优势
汇编
语言

充分利用32bit字长

32bit寄存器可用来寻址

与比例因子有关的寻址方式可用

使用新增的指令
实模式下混合的16bit与32bit指令举例:
adc
mov
sub
mov
mov
add
mov
eax, [di]
dword ptr dq_data, eax
ebx, edx
ah, byte_table[esi]
word_table[esi*2], ax
eax, array[ebx*4]
dword ptr result+4[ebx*8], edx
上机环境
命令行 PWB
MASM一系列版本
MASM32
VC++6.0
调试工具
DEBUG
DEBUG32
CODEVIEW
中间文件
LST文件
汇编
语言
CRF文件
MAP文件
汇编
语言
汇编
语言
第五章 循环与分支程序
从这章开始涉及编程方法与技巧,尽管所举例子可
能在高级语言中也出现过,学生并不陌生,但学生的困
难在于对这种表现形式的不习惯,特别是转移指令、循
环指令的用法。
高级语言的for while if else翻译过来也是一大堆这
样的形式,我们直接用汇编这样写,会比高级语言效率
更高。
对于处理一些特定的问题如地址表、逻辑尺,汇编
有其独特的优势。我们也会涉及一些经典算法如冒泡排
序、折半查找,重点让学生感受汇编与高级语言在表现
形式上的相同与不同。
汇编
语言
用高级伪指令实现分支和循环
.if/.else/.endif
.while/.endw
.repeat/.until
.break/.continue
标号的使用:
标号用来标识代码段中转移指令的目标位置,它有两种出现形式:
标号:
或者
目标指令
; 一个冒号,作用域仅限当前过程
标号::
目标指令
; 两个冒号,作用域是整个程序
在默认情况下,标号后跟一个冒号,作用域是当前过程,标号仅对
其所在过程内的语句可见,不同过程中的标号可以重名;
在少数情况下,后跟两个冒号的标号被声明成全局的:
……
main
proc
start::
……
; 全局标号,后跟两个冒号
ret
main
endp
end
start
标号的命名规范也与变量相同,除字母、数字(不能是首字符)、
下划线外,还可以使用@、$和?
L1:
L2:
……
cmp
jnl
inc
dec
jmp
mov
……
eax, ebx
L2
eax
ebx
L1
ecx, 0
; 向前跳转
; 向后跳转
高版本的MASM支持用@@取代标号,而不用给它们取名字:
……
@@:
cmp
eax, ebx
jnl
@F
; 向前跳转,@F表示本条指令后的第一个@@标号
inc
eax
dec
ebx
jmp
@B
; 向后跳转,@B表示本条指令前的第一个@@标号
@@:
mov
ecx, 0
……
用.if/.else/.endif实现分支
当需要进行较为复杂的比较(比如(a>b)&&(c<d))时,仅用基本
指令实现分支的源代码会比较长,结构也不够清晰。
高版本的MASM提供了用于轻松构造分支结构的.if/.else/.endif
等高级伪指令,它们其实是高级语言宏,与高级语言中的分支语句在语
法和语义上非常相似。
.if 条件表达式1
指令块1
[.elseif 条件表达式2]
指令块2
……
[.else]
指令块n
.endif
例:
eax == 0
array[esi*4] > eax
(ebx >= 1) && (ebx <= 10)
标志位判定表达式:
CARRY?
OVERFLOW?
PARITY?
SIGN?
ZERO?
例:
CARRY? || ZERO?
;
;
;
;
不能写成0 == eax
array是双字变量
不能写成(1 <= ebx) && (ebx <= 10)
短路求值
;
;
;
;
;
cf=1时为真
of=1时为真
pf=1时为真
sf=1时为真
zf=1时为真
操作符
!
< <= > >=
== !=
&
&&
||
.if伪指令的实现细节
例:
……
.data
szMsg BYTE
.code
……
mov
compare:
mov
.if
exit:
“My.obj - 0 error(s), 2 warning(s)”,0
ebx, 0
al, szMsg[ebx]
al == 0
; 遇到结束标志
jmp
exit
.elseif
al>='a' && al<='z' || al>='A' && al<='Z'
inc
esi
.elseif
al>='0' && al<='9'
inc
edi
.else
inc
edx
.endif
add
ebx, type szMsg
jmp
compare
ret
……
用.while/.repeat实现循环
.while 条件表达式
指令块
[.break [.if 退出条件]]
[.continue]
.endw
.repeat
指令块
[.break [.if 退出条件]]
[.continue]
.until 条件表达式 (.untilcxz [条件表达式])
条件表达式的值为“假”时继续循环,也就是说循环
直到条件表达式的值为“真”时结束。
例:统计字符串的长度
lpBYTE
szMsg
lpszMsg
……
typedef
.data
BYTE
lpBYTE
.code
……
mov
mov
.while
.endw
sub
……
PTR BYTE
"My.obj - 0 error(s), 2 warning(s)",0
szMsg
al, 0
esi, lpszMsg
[esi] != al
inc
esi
esi, lpszMsg
.while
1
.break
inc
esi
.endw
.if
[esi]==al
例:统计字符串的长度(换一种写法)
……
mov
esi, lpszMsg
mov
ecx, 0
dec
esi
.repeat
inc
ecx
inc
esi
.until
BYTE PTR [esi] == 0
dec
ecx
……
例:统计字符串中小写字母的个数
……
mov
mov
.while
esi, lpszMsg
ecx, 0
BYTE PTR [esi] != 0
mov
al, [esi]
inc
esi
.if
al<'a' || al>'z'
.continue
.endif
inc
ecx
.endw
……
C/C++中的循环与分支是如何实现的?
if … else
switch … case
for (i=0;i<10;i++)
{
…… }
while (i<10)
{
…… }
do { …… } while (i<10);
不同形式循环/分支的汇编格式有什么不同?效率上有
不同吗?
第六章 子程序结构
在介绍子程序的参数传递时,用堆栈传递参数或参
数地址是学生比较难掌握的,尤其是BP/EBP寄存器的
使用和带立即数的RET指令的使用。
嵌套和递归子程序设计对学生而言也有一定难度。
我们在平时练习和上机中加重了这方面的训练,在实验
中也特别设计了这方面的内容,并要求学生在实验报告
中分析子程序功能、参数传递机制、堆栈变化情况等。
汇编
语言
堆栈框架(活动记录)
00401032
00401033
00401035
00401036
00401037
00401038
00401039
0040103C
……
00401054
00401055
00401056
00401057
00401058
00401059
push
mov
push
push
push
push
mov
mov
ebp
ebp,esp
eax
edx
esi
edi
esi,[ebp+8]
edi,[ebp+12]
pop
pop
pop
pop
leave
ret
edi
esi
edx
eax
8
edi
esi
edx
eax
ebp
esp
ebp
返回地址
szMsg1的地址
szMsg2的地址
; mov esp,ebp
pop ebp
; 栈中的参数不再有用,+8跳过
结构伪操作的使用:
code2
segment
assume
cs:code2
stack_strc
save_bp
save_cs_ip
par3_addr
par2_addr
par1_addr
stack_strc
proadd
proadd
code2
汇编
语言
proc
……
……
endp
ends
end
far
start
struc
dw
dw
dw
dw
dw
ends
?
2 dup(?)
?
?
?
proadd
proc
push
mov
push
push
push
push
mov
mov
mov
mov
xor
far
bp
bp,
ax
cx
si
di
si,
di,
cx,
di,
ax,
add
add
loop
mov
pop
pop
pop
pop
pop
ret
endp
ax, [si]
si, 2
next
[di],ax
di
si
cx
ax
bp
6
sp
(sp) (di)
[bp].par1_addr
[bp].par2_addr
[di]
[bp].par3_addr
ax
next:
汇编
语言
proadd
(si)
(cx)
(ax)
(bp) (bp)
(ip)
(cs)
par3_addr 0016
par2_addr 0014
par1_addr 0000
0
(ds)
子程序的定义、声明和调用
子程序的定义:
功能增强的过程定义伪操作
子程序名 proc [距离][语言类型][可视区域][USES 寄存器列表,][参数名:类型]
LOCAL
……
子程序名 endp
局部变量列表
; 局部变量定义
; 子程序体
• 距离:NEAR或FAR,在实模式下用于标识调用程序和子程序是否
在同一代码段中;但保护模式下无所谓距离,这一项往往省略。
• 语言类型:与.model伪指令中的语言类型相同,可以是
c/basic/fortran/ pascal或stdcall/syscall。该项主要用
来决定子程序中参数的入栈顺序和子程序返回时堆栈的清除方式。
• 可视区域:可以取值public、private或export,用于说明子
程序的可见性。
• USES:后接寄存器列表,指示汇编编译器在子程序开始处生成
push指令保存所列的寄存器,在子程序返回之前生成pop指令恢复这
些寄存器。
• 参数和类型:参数用于在调用程序与子程序之间传递数据,参数不
能与全局变量和子程序中的局部变量重名,但不同子程序的参数可以
重名。
例:
Add_Two1
Add_Two1
Add_Two2
Add_Two2
str_compare
str_compare
proc
……
endp
v1:dword, v2:dword
proc pv1:ptr dword, pv2:ptr dword
local result
……
endp
proc USES eax edx esi edi,
string1:PTR BYTE,string2:PTR BYTE
……
ret
endp
子程序的声明:
子程序名
PROTO [距离][语言类型][可视区域][:参数类型]
例如:
Add_Two1
PROTO :dword,:dword
Add_Two2
PROTO :ptr dword,:ptr dword
str_compare
PROTO :PTR BYTE,:PTR BYTE
声明后的子程序可以先被调用,而后再定义。
如果先定义子程序而后再调用它,子程序声明也可以省略。
由系统提供的子程序的声明一般在头文件(.inc文件)中,例如
masm32下的user32.inc和kernel32.inc。
……
include c:\masm32\include\kernel32.inc
include c:\masm32\include\user32.inc
……
或者直接列写子程序原型,例如:
……
ExitProcess
GetLocalTime
PROTO :DWORD
PROTO :DWORD
; kernel32.inc
; kernel32.inc
; user32.inc
MessageBoxA
……
PROTO :DWORD,:DWORD,:DWORD,:DWORD
子程序的调用:
invoke 子程序名[,参数列表]
参数可以是立即数、寄存器、变量或变量地址等。参数传递由编译器
自动实现,不需要程序员的干预。
例:
invoke Add_Two1, var1,var2
Invoke Add_Two2, ADDR var1,ADDR var2
invoke str_compare, ADDR szMsg1,ADDR szMsg2
子程序的定义、声明和调用的关系是:
……
str_compare
PROTO :PTR BYTE,:PTR BYTE
; 声明
……
invoke
str_compare, ADDR szMsg1,ADDR szMsg2
; 调用
……
str_compare
proc
USES eax edx esi edi,
; 定义
string1:PTR BYTE,string2:PTR BYTE
……
str_compare
……
endp
例:
.386
.model flat, stdcall
.stack 4096
ExitProcess
proto, :dword
add_array
proto, :ptr dword, :dword
; 子程序声明
.data
dword 1000H,2000H,3000H,4000H,5000H,6000H
dword ?
array
sum
.code
main
proc
invoke Add_array,
addr array,
lengthof array
mov
sum,eax
invoke ExitProcess,0
main
endp
; 子程序调用
; 子程序调用
Add_array
proc
uses esi ecx,
ptrarray:ptr dword,
sizearray:dword
mov
mov
mov
esi,ptrarray
ecx,sizearray
eax,0
add
add
loop
ret
eax,[esi]
esi,4
again
again:
Add_array
endp
end
main
; 子程序定义
调用程序的工作:
调用程序main中的invoke伪指令“展开”为push指令和call
指令,即先将参数(实参)入栈,然后调用子程序,更具体地:
• 参数入栈是为了传参,这说明主程序与子程序之间的参数传递是通
过堆栈完成的。
• 参数传递不一定非要通过堆栈(可采用寄存器传参等其它方式),
但如果使用的是invoke后接实参列表的形式调用子程序,这一过程只
能通过堆栈进行。
•
如果参数的个数大于1,参数入栈还有一个顺序问题。
c
最先入栈参数
清除堆栈者
右
调
stdcall syscall
右
子
右
子
basic
左
子
fortran
pascal
左
子
左
子
第七章 高级汇编语言技术
高级汇编语言技术,宏汇编、重复汇编、条件汇
编的使用为简化程序结构提供很大便利,要求学生搞
清楚宏与子程序的区别,在实验中要求学生编制宏库
来扩展已有的指令系统。
宏定义 宏调用 宏展开 在列表文件中可看到
汇编
语言
第八章 I/O程序设计
查询 中断 DMA
工具: I/O指令
难点在于“中断”处理,它也是“机器”和“程序”
协同完成的一项工作。
中断向量表和中断过程
中断处理程序的作用和编写方法
内中断 外中断
Sound程序 计时程序 键盘模拟程序
汇编
语言
第十章 模块化程序设计
汇编和连接程序的功能
工程
汇编与高级语言连接要解决的问题
存储器分配 两种语言之间的控制传送
调用协议
C语言调用协议
汇编
语言
PASCAL语言调用协议
变量传送
实验设置与考核方式
 作业 (通过网络学堂提交)10%
 实验和实验报告 30%
 考试 (笔试、开卷)60%
作业内容
实验内容
考试内容
汇编
语言
基础性
综合性
开放性
作业的基础性
概念
原理
编程题目必须在机器上验证 不能纸上谈兵
 写出下列字符串的ASCII码(汉字写它的内码,查查
资料,什么是内码?或在机器上试一下)。
80x86汇编语言程序设计
Assembly language programs are often the smallest.
 在实模式下,逻辑地址(段地址:偏移地址)为
0B5C:001D,
(1)计算物理地址;
(2)对应这个物理地址,有几种可能的逻辑地址?
汇编
语言
 在实模式下,用debug调试test.exe的截屏如上:
• 存储器是如何分段的?数据段有多长?
• 此时刚执行完哪条指令?
• FLAGS中CF/OF/SF/ZF的值是多少,有什么含义?
• 在第一条指令PUSH DS执行之前,DS和ES会是多少?
汇编
语言
汇编
语言
 反汇编后的代码中用了哪些与数据有关的寻址方式?
划线的转移指令用了什么寻址方式?当前的EIP和位移量分
别是多少?这些转移有什么不同?
实验的综合性 验证性
实验报告分析实验结果、子程序功能、参数传递机制、堆
栈变化情况、算法效率等。
上机检查
答辩
实验一
带符号数的十六进制和十进制之间的转换。
要求:键盘输入,屏幕输出,有简单的菜单提示
16 10 ‘a’~’f’ 和 ’A’~’F’ 都可接收
10 16 十进制数可带正负号,123、 +123、-123都是合法
输入。
汇编
语言
实验二 三种排序算法的递归实现
要求:
1.完成冒泡、选择、快速三种排序算法
2.用汇编和C/C++两种语言编程,均要求递归实现
要写出自己的特色。
3.借此分析高级语言和汇编语言的优缺点,谈谈你用汇编
语言编程的经验和体会。
实验三 计时器设计
汇编
语言
要求:
1.设计一个计时器(图示),模拟计时过程(按键开始计
时,按键结束计时)
3.用你的计时器给某段程序计时,看看程序的执行时间
(可结合实验二)
实验四 建立一个宏(数学)库,扩展已有的指令系统。
要求:
1.宏库包含n的阶乘、n的开方、n的平方、n的绝对值、以2
为底n的对数、以10为底n的对数、2的n次幂、10的n次幂的
宏定义,运算结果仅取整数部分;
2. 尽量使用条件或重复等高级汇编技术;
3. 代码段中要有相应的宏调用,以检验宏定义的正确性;
4. 适当的输入输出提示。
汇编
语言
实验设置还可考虑趣味性
猜数游戏:有编号为 0# 1# 2# 3# 4# 5# 的 6 张卡片,每张卡
片上有一些数字(1~50):
0# 1
3 5 7 9
3 6 7 10
2# 4
5 6 7 12
11 13 15 17 19
11 14 15 18 19
13 14 15 20 21
21 23 25 27 29
22 23 26 27 30
22 23 28 29 30
31 33 35 37 39
31 34 35 38 39
31 36 37 38 39
41 43 45 47 49
42 43 46 47 50
44 45 46 47
3# 8
9 10 11 12
4# 16 17 18 19 20
5# 32 33 34 35 36
13 14 15 24 25
21 22 23 24 25
37 38 39 40 41
26 27 28 29 30
26 27 28 29 30
42 43 44 45 46
31 40 41 42 43
31 48 49 50
47 48 49 50
44 45 46 47
汇编
语言
1# 2
你首先想一个 1~50 之间的数(不要说出来),计算机从
0# 到 5# 依次出示 6 张卡片,并向你询问:“你心里想的数
是否出现在这些卡片中?”,计算机可根据你的回答猜出你
想的数。
计算机如何生成这些卡片?如何根据与你的一问一答猜出
你想的数?编程设计小游戏。
考试 开卷
个人体会与大家交流
 参考资料的选择
The Art of Assembly Language,Randy Hyde
http://webster.cs.ucr.edu/
IBM PC Assembly Language and Programming,Peter Abel
Intel 汇编语言程序设计(第4版),Kip R. Irvine 电子工业出版社
Computer Systems : A Programmer’s Perspective,
Randal E. Bryant
汇编
语言
David R. O’Hallaron
 建议学生多读程序(系统程序 样例程序),养成
编程的好习惯(命名 缩进 注释…)
汇编
语言
 养成学生自学的习惯
编译器的使用 机器码 扩展指令等
汇编
语言
 可适当打乱教材顺序,先讲程序结构
 要善于总结,也让学生勤于总结,找共性、
规律、原因
 要有更高的视野,…
汇编
语言
学生的收获:
“我对汇编真正感兴趣是从“会编”开始的。……
原来mov来mov去,其中竟还有一番天地,也需要如此之
多的技巧。”
“能在这么短的时间里,对一门复杂精深的课程有一
个初步的概念已经很不容易了,不管最后成绩如何,我都
能告诉自己,我是有收获的。”
学生在试验平台上设计了自己的指令系统和编译器
用汇编语言写了简易的C编译器
汇编
语言
讨论:
• 在课时压缩的情况下汇编应该怎样讲?
• 实模式、保护模式的内容如何分配?
• 学生在学习中有哪些反馈?主要困难是什么?
• ……
汇编
语言