钱晓捷,微机原理与接口技术 ·第 4版 —— 基于 IA-32处理器和 32位汇编语言第 4 章汇编语言程序设计
4.1分支程序结构
4.2 循环程序结构
4.3 子程序结构
4.4 Windows应用程序编程
4.5 与 C++语言的混合编程微机原理与接口技术
·

4
版机械工业出版社
4.1 分支程序结构
改变程序执行顺序,形成分支,循环,调用等程序结构是很常见的程序设计问题
高级语言采用 IF等语句表达条件,并根据条件是否成立转向不同的程序分支
汇编语言需要首先利用比较 CMP,测试 TEST,加减运算,逻辑运算等影响状态标志的指令形成条件然后利用条件转移指令判断由标志表达的条件,并根据标志状态控制程序转移到不同的程序段微机原理与接口技术
·

4
版机械工业出版社
4.1.1 无条件转移指令
程序代码在代码段
CS:指明代码段在主存中的段基地址
EIP:给出将要执行指令的偏移地址
程序顺序执行,处理器自动增量 EIP
程序控制转移,EIP随之改变
程序转移到另外的代码段,EIP和 CS都改变
控制转移类指令:改变 EIP( 有些也改变
CS),即改变程序执行顺序 ( 实现程序控制转移 ) 的指令本章学习 控制转移类指令微机原理与接口技术
·

4
版机械工业出版社
1,转移范围
段内转移在当前代码段范围内的程序转移不需更改 CS,只要改变 EIP( 偏移地址 )
近转移 ( Near),32位近转移 NEAR32,16位近转移 NEAR16
短转移 ( Short),转移范围在 127~ -128字节
段间转移从当前代码段跳转到另一个代码段需要更改 CS( 段地址 ) 和 EIP( 偏移地址 )
远转移 ( Far),48位远转移 FAR32,32位远转移 FAR16
微机原理与接口技术
·

4
版机械工业出版社
2,指令寻址方式
相对寻址方式提供目标地址相对于当前指令指针 EIP的位移量目标地址 ( 转移后的 EIP) =当前 EIP+位移量相对寻址都是段内转移,最常用,最灵活
直接寻址方式直接提供目标地址目标地址 ( 转移后的 CS和 EIP) =指令操作数
间接寻址方式指示寄存器或存储单元目标地址来自寄存器或存储单元,间接获得寄存器间接寻址:用寄存器保存目标地址存储器间接寻址:用存储单元保存目标地址目标地址 = 目的地址 = 转移地址微机原理与接口技术
·

4
版机械工业出版社
3,JMP指令
无条件转移:程序无条件改变执行顺序
JMP指令相当于高级语言的 goto语句
JMP label;程序转向 label标号指定的地址;段内相对寻址,段间直接寻址
JMP reg32/reg16;程序转向寄存器指定的地址;寄存器间接寻址
JMP mem32/mem16;程序转向存储单元指定的地址;存储器间接寻址微机原理与接口技术
·

4
版机械工业出版社
JMP指令的 4种类型
1,段内转移,相对寻址标号指明目标地址,指令代码包含位移量
2,段内转移,间接寻址通用寄存器或主存单元包含目标指令偏移地址
3,段间转移,直接寻址标号包含目标指令的段地址和偏移地址
4,段间转移,间接寻址
32位段用 3字存储单元包含目标地址
16位段用双字存储单元包含目标地址
MASM会根据存储模式等信息自动识别微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-1〕 无条件转移程序- 1; 数据段
00000000 00000000
nvar dword?; 代码段
00000000 EB 01
jmp labl1 ; 相对寻址
00000002 90
nop
00000003 E9 00000001
labl1,jmp near ptr labl2; 相对近转移
00000008 90
nop
00000009 B8 00000011 R
labl2,mov eax,offset labl3
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-1〕 无条件转移程序- 2
0000000E FF E0
jmp eax ; 寄存器间接寻址
00000010 90
nop
00000011 B8 00000022 R
labl3,mov eax,offset labl4
00000016 A3 00000000 R
mov nvar,eax
0000001B FF 25 00000000 R
jmp nvar ; 存储器间接寻址
00000021 90
nop
labl4:
mov ebx,offset nvar
jmp near ptr [ebx];数据的寄存器间接寻址数据的存储器直接寻址微机原理与接口技术
·

4
版机械工业出版社
4.1.2 条件转移指令
根据指定的条件确定程序是否发生转移
Jcc label;条件满足,发生转移;否则,顺序执行下条指令
LABEL表示目标地址,采用段内相对寻址
32位 IA-32处理器:达到 32位的全偏移量
16位 80x86处理器,-128~ +127间的短转移条件转移指令不影响标志,但要利用标志
cc表示利用标志判断的条件,16种,两类单个标志状态作为条件两数大小关系作为条件微机原理与接口技术
·

4
版机械工业出版社转移条件 cc:单个标志状态
JZ/JE ZF=1 Jump if Zero/Equal
JNZ/JNE ZF=0 Jump if Not Zero/Not Equal
JS SF=1 Jump if Sign
JNS SF=0 Jump if Not Sign
JP/JPE PF=1 Jump if Parity/Parity Even
JNP/JPO PF=0 Jump if Not Parity/Parity Odd
JO OF=1 Jump if Overflow
JNO OF=0 Jump if Not Overflow
JC CF=1 Jump if Carry
JNC CF=0 Jump if Not Carry
多个助记符方便记忆微机原理与接口技术
·

4
版机械工业出版社转移条件 cc:两数大小关系
JB/JNAE CF=1 Jump if Below/Not Above or Equal
JNB/JAE CF=0 Jump if Not Below/Above or Equal
JBE/JNA CF=1或 ZF=1 Jump if Below/Not Above
JNBE/JA CF=0且 ZF=0 Jump if Not Below or Equal/Above
JL/JNGE SF≠OF
Jump if Less/Not Greater or Equal
JNL/JGE SF=OF
Jump if Not Less/Greater or Equal
JLE/JNG ZF≠OF 或 ZF=1
Jump if Less or Equal/Not Greater
JNLE/JG SF=OF且 ZF=0
Jump if Not Less or Equal/Greater
微机原理与接口技术
·

4
版机械工业出版社
1,单个标志状态作为条件的条件转移指令
JZ(JE)和 JNZ(JNE):利用零位标志 ZF
判断结果是零 ( 相等 ) 还是非零 ( 不等 )
JS和 JNS:利用符号标志 SF
判断结果是负还是正
JO和 JNO:利用溢出标志 OF
判断结果是溢出还是没有溢出
JP(JPE)和 JNP(JPO):利用奇偶标志 PF
判断结果低字节,1” 的个数是偶数还是奇数
JC和 JNC:利用进位标志 CF
判断结果是有进位 ( 为 1) 还是无进位 ( 为 0)
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-2〕 个数折半程序- 1
mov eax,885 ; 假设一个数据
shr eax,1 ; 数据右移进行折半
jnc goeven; 余数为 0,即 CF= 0条件成立,转移
add eax,1; 否则余数为 1,即 CF= 1,进行加 1操作
goeven,call dispuid ; 显示结果
443
运行结果微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-2〕 个数折半程序- 2
mov eax,886 ; 假设一个数据
shr eax,1 ; 数据右移进行折半
jc goodd; 余数为 1,即 CF= 1条件成立,转移到分支体,进行加 1操作
jmp goeven; 余数为 0,即 CF= 0,不需要处理,转移到显示 !
goodd,add eax,1 ; 进行加 1操作
goeven,call dispuid ; 显示结果
jnc goeven 何不合二为一?
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-2〕 个数折半程序- 3
mov eax,887 ; 假设一个数据
shr eax,1 ; 数据右移进行折半
adc eax,0; 余数= CF= 1,进行加 1操作;余数= CF= 0,没有加 1
call dispuid ; 显示结果
mov eax,888 ; 假设一个数据
add eax,1 ; 个数加 1
rcr eax,1 ; 数据右移进行折半
call dispuid ; 显示结果 改进算法消除分支微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-3〕 位测试程序- 1; 数据段
no_msg byte 'Not Ready!',0
yes_msg byte 'Ready to Go!',0; 代码段
mov eax,56h ; 假设一个数据
test eax,02h ; 测试 D1位 (D1= 1,其他位为 0)
jz nom ; D1= 0条件成立,转移
mov eax,offset yes_msg; D1= 1,显示准备好
jmp done ; 跳转过另一个分支体 !
nom,mov eax,offset no_msg ; 显示没有准备好
done,call dispmsg
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-3〕 位测试程序- 2; 数据段
no_msg byte 'Not Ready!',0
yes_msg byte 'Ready to Go!',0; 代码段
mov eax,56h ; 假设一个数据
test eax,02h ; 测试 D1位 (D1= 1,其他位为 0)
jnz yesm ; D1= 1条件成立,转移
mov eax,offset no_msg; D1= 0,显示没有准备好
jmp done ; 跳转过另一个分支体 !
yesm,mov eax,offset yes_msg ; 显示准备好
done,call dispmsg
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-4〕 奇校验程序
call readc ; 键盘输入,AL=返回值
call dispcrlf ; 回车换行 ( 用于分隔 )
call dispbb ; 以二进制形式显示数据
call dispcrlf ; 回车换行 ( 用于分隔 )
and al,7fh; 最高位置,0”,其他位不变; 同时标志 PF反映,1” 的个数
jnp next; 个数为奇数,不需处理,转移
or al,80h; 个数为偶数,最高位置,1”,其他位不变
next,call dispbb ; 显示含校验位的数据微机原理与接口技术
·

4
版机械工业出版社
2,两数大小关系作为条件的条件转移指令
无符号数用高 ( Above),低 ( Below)
低于 ( 不高于等于 ),JB( JNAE)
不低于 ( 高于等于 ),JNB( JAE)
低于等于 ( 不高于 ),JBE( JNA)
不低于等于 ( 高于 ),JNBE( JA)
有符号数用大 ( Greater),小 ( Less)
小于 ( 不大于等于 ),JL( JNGE)
不小于 ( 大于等于 ),JNL( JGE)
小于等于 ( 不大于 ),JLE( JNG)
不小于等于 ( 大于 ),JNLE( JG)
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-5〕 数据比较程序- 1; 数据段
in_msg1 byte 'Enter a number,',0
in_msg2 byte 'Enter another number,',0
out_msg1 byte 'Two numbers are equal,',0
out_msg2 byte 'The less number is,',0
out_msg3 byte 13,10,'The greater number is,',0; 代码段
mov eax,offset in_msg1 ; 提示输入
call dispmsg
call readsid ; 输入第一个数据
mov ebx,eax ; 保存到 EBX
mov eax,offset in_msg2 ; 提示输入
call dispmsg
call readsid ; 输入第二个数据
mov ecx,eax ; 保存到 ECX
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-5〕 数据比较程序- 2
cmp ebx,ecx ; 二个数据进行比较
jne nequal ; 两数不相等,转移
mov eax,offset out_msg1
call dispmsg ; 显示两数相等
mov eax,ebx
call dispsid ; 显示相等的数据
jmp done ; 转移到结束
nequal,jl first; EBX较小,不需要交换,转移
xchg ebx,ecx; EBX保存较小数,ECX保存较大数微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-5〕 数据比较程序- 3
first,mov eax,offset out_msg2; 显示较小数
call dispmsg
mov eax,ebx ; 较小数在 EBX中
call dispsid
mov eax,offset out_msg3; 显示较大数
call dispmsg
mov eax,ecx ; 较大数在 ECX中
call dispsid
done:
微机原理与接口技术
·

4
版机械工业出版社
4.1.3 单分支结构
只有一个分支的程序类似高级语言的 IF-THEN语句结构
注意采用正确的条件转移指令当条件满足 ( 成立 ),发生转移,跳过分支体条件不满足,顺序向下执行分支体
条件转移指令与高级语言的 IF语句正好相反
IF语句是条件成立,执行分支体微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-6〕 求绝对值程序; 代码段
call readsid; 输入一个有符号数,从 EAX返回值
cmp eax,0 ; 比较 EAX与 0
jge nonneg; 条件满足,AX≥ 0,转移
neg eax; 条件不满足,AX< 0,为负数; 需求补得正值
nonneg,call dispuid ; 分支结束,显示结果示意图微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-7〕 字母判断程序
call readc; 输入一个字符,从 AL返回值
cmp al,'A’ ; 与大写字母 A比较
jb done; 比大写字母 A小,不是大写字母,转移
cmp al,'Z’ ; 与大写字母 Z比较
ja done; 比大写字母 Z大,不是大写字母,转移
or al,20h ; 转换为小写
call dispcrlf ; 回车换行
call dispc ; 显示小写字母
done:
微机原理与接口技术
·

4
版机械工业出版社
4.1.4 双分支结构
双分支程序结构有两个分支,条件为真执行一个分支;条件为假,执行另一个分支相当于高级语言的 IF-THEN-ELSE语句
顺序执行的分支体 1最后一定要有一条 JMP指令跳过分支体 2
JMP指令必不可少,实现结束前一个分支回到共同的出口作用
双分支结构有时可以改变为单分支结构事先执行其中一个分支 ( 选择出现概率较高的分支 )
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-8〕 显示数据最高位程序- 1; 数据段
dvar dword 0bd630422h ; 假设一个数据; 代码段
mov ebx,dvar
shl ebx,1 ; EBX最高位移入 CF标志
jc one; CF= 1,即最高位为 1,转移
mov al,'0'; CF= 0,即最高位为 0,AL←' 0'
jmp two ; 一定要跳过另一个分支
one,mov al,'1' ; AL←' 1'
two,call dispc ; 显示示意图双分支结构微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-8〕 显示数据最高位程序- 2
mov ebx,dvar
mov al,'0'; 假设最高位为 0,AL←' 0'
shl ebx,1 ; EBX最高位移入 CF标志
jnc two; CF= 0,即最高位为 0,转移
mov al,'1'; CF= 1,即最高位为 1,AL←' 1'
two,call dispc ; 显示单分支结构微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-9〕 有符号数运算溢出程序; 数据段
dvar1 dword 1234567890 ; 假设两个数据
dvar2 dword -999999999
dvar3 dword?
okmsg byte 'Correct!',0 ; 正确信息
errmsg byte 'ERROR ! Overflow!',0 ; 错误信息; 代码段
mov eax,dvar1
sub eax,dvar2 ; 求差
jo error ; 有溢出,转移
mov dvar3,eax ; 无溢出,保存差值
mov eax,offset okmsg ; 显示正确
jmp disp
error,mov eax,offset errmsg; 显示错误
disp,call dispmsg
微机原理与接口技术
·

4
版机械工业出版社
4.2 循环程序结构
三个部分组成:
循环初始 —— 为开始循环准备必要的条件,如循环次数,循环体需要的初始值等;
循环体 —— 重复执行的程序代码,其中包括对循环条件的修改等;
循环控制 —— 判断循环条件是否成立,决定是否继续循环
,先判断,后循环,的循环程序结构对应高级语言的 WHILE语句
,先循环,后判断,的循环程序结构对应高级语言的 DO语句示意图微机原理与接口技术
·

4
版机械工业出版社
4.2.1 循环指令
LOOP label;ECX←ECX - 1;若 ECX≠ 0,循环到 LABEL;否则,顺序执行
JECXZ label;ECX= 0,转移;否则顺序执行
目标地址采用相对短转移
实地址存储模型使用 CX作为计数器
DEC ECX
JNZ label
CMP ECX,0
JZ label
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-10〕 数组求和程序
mov ecx,lengthof array; ECX=数组元素个数
xor eax,eax ; 求和初值为 0
mov ebx,eax ; 数组指针为 0
again,add eax,array[ebx*(type array)]; 求和
inc ebx ; 指向下一个数组元素
loop again
mov sum,eax ; 保存结果
call dispsid ; 显示结果循环体循环控制循环初始微机原理与接口技术
·

4
版机械工业出版社
4.2.2 计数控制循环
通过次数控制循环利用 LOOP指令属于计数控制常见是,先循环,后判断,循环结构
计数可以减量进行,即减到 0结束
计数可以增量进行,即达到规定值结束循环程序结构的关键是如何控制循环微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-11〕 简单加密解密程序- 1; 数据段
key byte 234
bufnum = 255
buffer byte bufnum+1 dup(0); 定义键盘输入需要的缓冲区
msg1 byte 'Enter messge,',0
msg2 byte 'Encrypted message,',0
msg3 byte 13,10,'Original messge,',0; 代码段
mov eax,offset msg1 ; 提示输入字符串
call dispmsg
mov eax,offset buffer ; 设置入口参数 EAX
call readmsg ; 调用输入字符串子程序
push eax ; 字符个数保存进入堆栈微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-11〕 简单加密解密程序- 2
mov ecx,eax; ECX=实际输入的字符个数,作为循环的次数
xor ebx,ebx ; EBX指向输入字符
mov al,key ; AL=加密关键字
encrypt,xor buffer[ebx],al ; 异或加密
inc ebx
dec ecx ; 等同于指令,loop encrypt
jnz encrypt ; 处理下一个字符
mov eax,offset msg2
call dispmsg
mov eax,offset buffer ; 显示密文
call dispmsg
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-11〕 简单加密解密程序- 3
pop ecx; 从堆栈弹出字符个数,作为循环的次数
xor ebx,ebx ; EBX指向输入字符
mov al,key ; AL=解密关键字
decrypt,xor buffer[ebx],al ; 异或解密
inc ebx
dec ecx
jnz decrypt ; 处理下一个字符
mov eax,offset msg3
call dispmsg
mov eax,offset buffer; 显示明文
call dispmsg
示意图微机原理与接口技术
·

4
版机械工业出版社
4.2.3 条件控制循环
根据条件决定是否进行循环需要使用有条件转移指令实现多见,先判断,后循环,结构
先行判断的条件控制循环程序很像双分支结构主要分支需要重复执行多次
( JMP的目标位置是循环开始 )
另一个分支用于跳出这个循环
先行循环的条件控制循环程序类似单分支结构,循环体就是分支体顺序执行就跳出循环微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-12〕 字符个数统计程序; 数据段
string byte ‘ Do you have fun with Assembly?’,0; 以 0结尾的字符串; 代码段
xor ebx,ebx; EBX用于记录字符个数,也用于指向字符的指针
again,mov al,string[ebx]
cmp al,0; 用指令,test al,al” 更好
jz done
inc ebx ; 个数加 1
jmp again ; 继续循环
done,mov eax,ebx ; 显示个数
call dispuid
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-13〕 字符剔除程序- 1
mov eax,offset string; 显示处理前字符串
call dispmsg
mov esi,offset string
outlp,cmp byte ptr [esi],0; 外循环,先判断后循环
jz done ; 为 0结束
again,cmp byte ptr [esi],' ' ; 是否是空格
jnz next ; 不是空格继续循环
mov edi,esi ; 是空格,剔除空格分支
inlp,inc edi ; 该分支是循环程序
mov al,[edi] ; 前移一个位置
mov [edi-1],al
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-13〕 字符剔除程序- 2
cmp byte ptr [edi],0; 内循环,先循环后判断
jnz inlp ; 内循环结束处
jmp again; 再次判断是否为空格 ( 处理连续空格 )
next,inc esi; 继续对后续字符进行判断处理
jmp outlp ; 外循环结束处
done,mov eax,offset string; 显示处理后字符串
call dispmsg
微机原理与接口技术
·

4
版机械工业出版社
4.3 子程序结构
经常用到的应用问题编写成一个通用子程序
大型处理过程分解成能够解决的模块
使用子程序可以使程序的结构更为清楚程序的维护更为方便有利于大程序开发时的多个程序员分工合作子程序 ( Subroutine)
=函数 ( Function)
=过程 ( Procedure)
微机原理与接口技术
·

4
版机械工业出版社
4.3.1 子程序指令
子程序,与主程序分开的,完成特定功能的一段程序
当 主程序 ( 调用程序 )
执行调用指令 CALL调用子程序
子程序 ( 被调用程序 )
执行返回指令 RET返回主程序
CALL label
主程序
RET
子程序回到 CALL指令后的指令处微机原理与接口技术
·

4
版机械工业出版社
1,子程序调用指令 CALL
CALL指令用在主程序中,实现子程序的调用
分成段内调用 ( 近调用 ) 和段间调用 ( 远调用 )
目标地址采用相对寻址,直接寻址或间接寻址
入栈返回地址:将 CALL下条指令的地址压入堆栈
CALL label;调用标号指定的子程序
CALL reg16/reg32;调用寄存器指定地址的子程序
CALL mem16/mem32;调用存储单元指定地址的子程序微机原理与接口技术
·

4
版机械工业出版社
2,子程序返回指令 RET
RET指令用在子程序结束,实现返回主程序
RET;无参数返回:出栈返回地址
RET i16;有参数返回:出栈返回地址;ESP←ESP + i16
MASM会根据存储模型等信息确定子程序的远近调用,并相应产生返回指令微机原理与接口技术
·

4
版机械工业出版社
3,过程定义伪指令
MASM利用过程定义伪指令获得子程序信息过程名 PROC
;过程体过程名 ENDP;过程名为符合语法的标识符
PROC后面可加参数,NEAR或 FAR
简化段定义源程序格式中,通常不需指定微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-14〕 子程序调用程序- 1; 代码段,主程序
00000000 B8 00000001
mov eax,1
00000005 BD 00000005
mov ebp,5
0000000A E8 00000016
call subp ; 子程序调用
0000000F B9 00000003
retp1,mov ecx,3
00000014 BA 00000004
retp2,mov edx,4
00000019 E8 00000000 E
call disprd
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-14〕 子程序调用程序- 2; 子程序
subp proc ; 过程定义,过程名为 subp
push ebp
mov ebp,esp
mov esi,[ebp+4]; ESI= CALL下条指令 (标号 RETP1)偏移地址
mov edi,offset retp2; EDI= 标号 RETP2的偏移地址
mov ebx,2
pop ebp ; 弹出堆栈,保持堆栈平衡
ret ; 子程序返回
subp endp ; 过程结束
MOV [EBP+4],EDI
示意图微机原理与接口技术
·

4
版机械工业出版社
4.3.2 子程序设计
子程序的编写方法与主程序一样
但需要留意几个问题:
利用过程定义,获得子程序名和调用属性
RET指令返回主程序,CALL指令调用子程序
压入和弹出操作要成对使用,保持堆栈平衡
开始保护寄存器,返回前相应恢复
安排在代码段的主程序之外
子程序允许嵌套和递归最好有完整的注释 难点是参数传递微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-15〕 十六进制显示程序- 1
mov eax,1234abcdh ; 假设一个数据
xor ebx,ebx
mov ecx,8 ; 8位十六进制数
again,rol eax,4 ; 高 4位循环移位进入低 4位
push eax
call htoasc ; 调用子程序
mov regd+4[ebx],al ; 保存转换后的 ASCII码
pop eax
inc ebx
dec ecx
jnz again
mov eax,offset regd
call dispmsg ; 显示微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-15〕 十六进制显示程序- 2; 子程序
htoasc proc; 将 AL低 4位表达的一位十六进制数转换为 ASCII码
and al,0fh ; 只取 AL的低 4位
or al,30h ; AL高 4位变成 3
cmp al,39h ; 是 0~ 9,还是 A~ F
jbe htoend
add al,7 ; 是 A~ F,ASCII码再加上 7
htoend,ret ; 子程序返回
htoasc endp
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-15〕 十六进制显示程序- 3; 子程序
htoasc proc
and eax,0fh ; 取 AL低 4位
mov al,ASCII[eax] ; 换码
ret; 子程序的局部数据 ( 只读 )
ASCII byte '0123456789ABCDEF'
htoasc endp
EAX=1234ABCDH
运行结果微机原理与接口技术
·

4
版机械工业出版社
4.3.3 参数传递
主程序与子程序间通过参数传递建立联系入口参数 (输入参数 ):主程序 → 子程序出口参数 (输出参数 ):子程序 → 主程序
传递参数的多少反映程序模块间的耦合程度
参数的具体内容数据本身 ( 传递数值 )
数据的存储地址 ( 传递地址,传递引用 )
参数传递方法寄存器变量堆栈微机原理与接口技术
·

4
版机械工业出版社
1,寄存器传递参数
最简单和常用的参数传递方法
把参数存于约定的寄存器少量数据直接传递数值大量数据只能传递地址
带有出口参数的寄存器不能保护和恢复
带有入口参数的寄存器可以保护,也可以不保护,但最好能够保持一致微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-16〕 有符号十进制数显示程序- 1
转换的算法如下:
( 1) 首先判断数据是零,正数或负数,是零显示
,0” 退出
( 2) 是负数,显示负号,-,,求数据的绝对值
( 3) 接着数据除以 10,余数为十进制数码,加 30H
转换为 ASCII码保存
( 4) 重复 ( 3) 步,直到商为 0结束
( 5) 依次从高位开始显示各位数字微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-16〕 有符号十进制数显示程序- 2; 数据段
array dword 1234567890,-1234,0,1,...
writebuf byte 12 dup(0) ; 显示缓冲区; 代码段
mov ecx,lengthof array
mov ebx,0
again,mov eax,array[ebx*4] ; EAX=入口参数
call write ; 调用子程序,显示一个数据
call dispcrlf ; 换行以便显示下一个数据
inc ebx
dec ecx
jnz again 寄存器传递参数微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-16〕 有符号十进制数显示程序- 3; 显示有符号十进制数的子程序
write proc ; EAX=入口参数
push ebx ; 保护寄存器
push ecx
push edx
mov ebx,offset writebuf ; EBX指向显示缓冲区
test eax,eax ; 判断数据是零,正数或负数
jnz write1 ; 不是零,跳转
mov byte ptr [ebx],'0' ; 是零,设置,0”
inc ebx
jmp write5 ; 转向显示
write1,jns write2 ; 是正数,跳转
mov byte ptr [ebx],'-' ; 是负数,设置负号
inc ebx
neg eax ; 数据求补 ( 绝对值 )
寄存器传递参数微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-16〕 有符号十进制数显示程序- 4
write2,mov ecx,10
push ecx ; 10压入堆栈,作为退出标志
write3,cmp eax,0 ; 数据 ( 商 ) 为零,转向保存
jz write4
xor edx,edx ; 零位扩展被除数为 EDX.EAX
div ecx ; 数据除以 10,EDX.EAX÷ 10
add edx,30h ; 余数 ( 0~ 9) 转换为 ASCII码
push edx ; 数据先低位后高位压入堆栈
jmp write3
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-16〕 有符号十进制数显示程序- 5
write4,pop edx ; 数据先高位后低位弹出堆栈
cmp edx,ecx ; 是结束标志 10,转向显示
je write5
mov [ebx],dl ; 数据保存到缓冲区
inc ebx
jmp write4
write5,mov byte ptr [ebx],0; 显示内容加上结尾标志
mov eax,offset writebuf
call dispmsg
pop edx ; 恢复寄存器
pop ecx
pop ebx
ret ; 子程序返回
write endp
微机原理与接口技术
·

4
版机械工业出版社
2,共享变量传递参数
子程序和主程序使用同一个变量名存取数据
如果变量定义和使用不在同一个程序模块中,
需要利用 PUBLIC,EXTREN声明
共享变量传递参数,子程序的通用性较差
特别适合在多个程序段间,尤其在不同的程序模块间传递数据微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-17〕 有符号十进制数输入程序- 1
十进制有符号整数转换为补码的算法如下:
( 1) 判断输入了正数,还是负数,用一个寄存器记录
( 2) 判断下一个字符是否为有效数码字符无效,提示错误重新输入,并转向 ( 1)
字符有效,继续
( 3) 字符有效,减 30H转换为二进制数;然后将前面输入的数值乘 10,并与刚输入的数字相加得到新的数值
( 4) 判断输入的数据是否超出有效范围超出范围,提示错误重新输入,并转向 ( 1)
没有超出范围,则继续
( 5) 重复 ( 2) ~ ( 4) 步,输入字符都有效,一直处理完
( 6) 是负数进行求补,转换成补码;否则直接将数值保存微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-17〕 有符号十进制数输入程序- 2; 数据段
count = 10
array dword count dup(0)
temp dword?
readbuf byte 30 dup(0); 代码段
mov ecx,count
mov ebx,offset array
again,call read ; 调用子程序,输入一个数据
mov eax,temp ; 获得出口参数
mov [ebx],eax ; 存放到数据缓冲区
add ebx,4
dec ecx
jnz again 共享变量传递参数微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-17〕 有符号十进制数输入程序- 3; 输入有符号十进制数的子程序
read proc; 出口参数:变量 TEMP=补码表示的二进制数值
push eax ; 说明:负数用,-,引导
push ebx
push ecx
push edx
read0,mov eax,offset readbuf
call readmsg ; 输入一个字符串
test eax,eax
jz readerr ; 没有输入数据,错误
cmp eax,12
ja readerr ; 输入超过 12个字符,错误微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-17〕 有符号十进制数输入程序- 4
mov edx,offset readbuf ; EDX指向输入缓冲区
xor ebx,ebx ; EBX保存结果
xor ecx,ecx ;ECX为正负标志,0为正,- 1为负
mov al,[edx] ; 取一个字符
cmp al,'+' ; 是,+,,继续
jz read1
cmp al,'-' ; 是,-,,设置- 1标志
jnz read2
mov ecx,-1
read1,inc edx ; 取下一个字符
mov al,[edx]
test al,al ; 是结尾 0,转向求补码
jz read3
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-17〕 有符号十进制数输入程序- 5
read2,cmp al,'0' ; 不是 0~ 9之间的数码,错误
jb readerr
cmp al,'9'
ja readerr
sub al,30h ; 是 0~ 9之间的数码,转换
imul ebx,10 ; 原数值乘 10,EBX= EBX× 10
jc readerr ; CF= 1,乘积溢出,出错
movzx eax,al ; 零位扩展,便于相加
add ebx,eax ; 原数乘 10后,与新数码相加
cmp ebx,80000000h; 数据超过 231,出错
jbe read1 ; 继续转换下一个数位微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-17〕 有符号十进制数输入程序- 6
readerr,mov eax,offset errmsg ; 显示出错信息
call dispmsg
jmp read0;
read3,test ecx,ecx ; 判断是正数还是负数
jz read4
neg ebx ; 是负数,进行求补
jmp read5
read4,cmp ebx,7fffffffh ; 正数超过 231-1,出错
ja readerr
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-17〕 有符号十进制数输入程序- 7
read5,mov temp,ebx ; 设置出口参数
pop edx
pop ecx
pop ebx
pop eax
ret ; 子程序返回
errmsg byte 'Input error,enter again,',0
read endp
共享变量传递参数微机原理与接口技术
·

4
版机械工业出版社
3,堆栈传递参数
主程序将入口参数压入堆栈,子程序从堆栈中取出参数
出口参数通常不使用堆栈传递
高级语言进行函数调用时提供的参数,实质也利用堆栈传递
采用堆栈传递参数是程式化的,它是编译程序处理参数传递,以及汇编语言与高级语言混合编程时的常规方法微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-18〕 计算有符号数平均值程序- 1; 数据段
array dword 675,354,-34,...; 代码段
push lengthof array ; 压入数据个数
push offset array ; 压数组的偏移地址
call mean; 调用求平均值子程序;出口参数,EAX=平均值 ( 整数部分 )
add esp,8; 平衡堆栈 ( 压入了 8个字节数据 )
call dispsid ; 显示堆栈传递参数微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-18〕 计算有符号数平均值程序- 2; 计算 32位有符号数平均值子程序
mean proc; 入口参数:顺序压入数据个数和数组偏移地址
push ebp ;出口参数,EAX=平均值
mov ebp,esp
push ebx ; 保护寄存器
push ecx
push edx
mov ebx,[ebp+8] ; EBX=取出的偏移地址
mov ecx,[ebp+12] ; ECX=取出的数据个数
xor eax,eax ; EAX保存和值
xor edx,edx ; EDX=指向数组元素堆栈传递参数微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-18〕 计算有符号数平均值程序- 3
mean1,add eax,[ebx+edx*4] ; 求和
add edx,1 ; 指向下一个数据
cmp edx,ecx ; 比较个数
jb mean1 ; 循环
cdq ; 将累加和 EAX符号扩展到 EDX
idiv ecx ; 有符号数除法,EAX=平均值
pop edx ; 恢复寄存器
pop ecx
pop ebx
pop ebp
ret
mean endp
示意图求和溢出与个数为 0的问题微机原理与接口技术
·

4
版机械工业出版社
4.3.4 程序模块
程序分段,子程序等是进行程序模块化
开发大型程序时采用的方法子程序模块子程序库库文件包含宏汇编源文件包含微机原理与接口技术
·

4
版机械工业出版社
1,子程序模块
子程序单独编写,汇编形成目标模块 OBJ文件
连接时输入子程序模块文件名
用共用伪指令 PUBLIC和外部伪指令 EXTERN声明
PUBLIC 标识符 [,标识符? ];定义标识符的模块使用
EXTERN 标识符,类型 [,标识符,类型? ];调用标识符的模块使用
子程序在代码段,与主程序文件采用相同的存储模型,没有开始执行和结束执行点
处理好子程序与主程序之间的参数传问题微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-19〕 数据输入输出程序- 1; eg0419s.asm( 子程序文件 )
include io32.inc
public read,write,mean ; 子程序共用
extern temp:dword ; 外部变量
.data ; 定义的变量集中起来
writebuf byte 12 dup(0) ; 显示缓冲区
readbuf byte 30 dup(0)
.code ; 代码段
write proc c ; 明确采用 C语言规范
; 输出子程序
read proc c
; 输入子程序
mean proc c
; 计算平均值子程序
end
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-19〕 数据输入输出程序- 2; eg0419.asm( 主程序文件 )
include io32.inc
extern read:near,write:near,mean:near; 外部子程序
public temp ; 变量共用
.data
count = 10
array dword count dup(0)
temp dword?
msg1 byte 'Enter 10 numbers:',13,10,0
msg2 byte 'The mean is,',0
.code
start,mov eax,offset msg1 ; 提示输入 10个数据
call dispmsg
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-19〕 数据输入输出程序- 3
xor ebx,ebx
mov ecx,count ; ECX=数据个数
again,call read; 调用子程序,输入一个数据
mov eax,temp; 获得出口参数
mov array [ebx*4],eax
add ebx,1
cmp ebx,count
jb again
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-19〕 数据输入输出程序- 4
push ecx ; 传递参数
push offset array
call mean ; 调用子程序,求平均值
add esp,8
mov ebx,eax ; EAX返回值转存到 EBX
mov eax,offset msg2 ; 提示输出平均值
call dispmsg
mov eax,ebx ; 提示输出平均值
call write ; 调用子程序,显示平均值
exit 0
end start
微机原理与接口技术
·

4
版机械工业出版社
2,子程序库
子程序库:统一管理子程序模块
遵循更加严格的子程序模块要求
子程序文件编写完成,汇编形成目标模块
利用库管理工具程序 LIB.EXE:把子程序模块逐个加入到子程序库 (,LIB)
使用子程序库:在连接主程序模块时提供子程序库文件名操作演示微机原理与接口技术
·

4
版机械工业出版社
3,库文件包含
直接在主程序源文件中用库文件包含伪指令
INCLUDELIB说明
不用在连接时输入库文件名
INCLUDELIB 文件名
子程序库文件名要符合操作系统规范必要时含有路径,用于指明文件的存储位置如果没有路径名,汇编程序将在默认目录,当前目录和指定目录下寻找微机原理与接口技术
·

4
版机械工业出版社
4,宏汇编
宏 ( Macro),具有宏名的一段汇编语句序列
宏需要先定义宏名 MACRO 形参表
;宏定义体
ENDM
然后程序中进行宏调用宏名 实体参数
在汇编时,宏指令被汇编程序用宏定义的代码序列替代,实现宏展开微机原理与接口技术
·

4
版机械工业出版社宏汇编示例
宏定义
WriteString macro msg
push eax
lea eax,msg
call dispmsg
pop eax
endm
宏展开
push eax
lea eax,msg
call dispmsg
pop eax
宏调用
WriteString msg
微机原理与接口技术
·

4
版机械工业出版社
5,源文件包含
INCLUDE 文件名
将 INCLUDE伪指令指定的文本文件内容插入源程序
可以包含任何文本文件一些常用的或有价值的宏定义存放在,MAC宏定义文件各种常量定义,声明语句等组织在,INC包含文件常用的子程序形成,ASM汇编语言源文件
利用 INCLUDE伪指令包含其他文件,其实质仍然是一个源程序,只不过是分在了几个文件书写
组合两种文件包含,以及宏汇编等方法,可以精简程序框架,简化程序设计
IO32.INC
微机原理与接口技术
·

4
版机械工业出版社
4.4 Windows应用程序编程
汇编语言可以编写 32位 Windows应用程序调用 Windows的应用程序接口 API
运行于 Windows操作系统平台
可以利用 Windows的高级特性,生成的可执行文件相对较小,性能更高
从更深层次理解 Windows运行机制及程序设计思想微机原理与接口技术
·

4
版机械工业出版社
4.4.1 操作系统函数调用
操作系统以其提供的系统函数 ( 系统功能
System function) 支持程序员进行编程
Windows的系统函数 ( 功能 ) 以动态连接库
DDL( Dynamic-Link Library) 形式提供,
利用其应用程序接口 API( Application
Program Interface) 调用 DDL库中的函数
API是一些类型,常量和函数的集合,提供了编程中使用库函数的途径
Win16,16位 Windows的 API
Win32,32位 Windows的 API
微机原理与接口技术
·

4
版机械工业出版社
1,动态连接库
静态连接,连接程序从库文件中抽取需要的子程序插入到最终的可执行代码中
动态连接,程序运行时才将代码加载到主存
动态连接库,保存程序运行时需要重复使用的代码的文件
3个最重要的 Windows动态连接库
KERNEL32.DLL:主要处理内存管理和进程调度
USER32.DLL:主要控制用户界面
GDI32.DLL:负责图形方面的操作
导入库 ( Import Library),程序开发的连接阶段使用,与一个动态连接库 DLL对应微机原理与接口技术
·

4
版机械工业出版社
2,MASM的高级语言特性
条件控制伪指令:
.IF,ELSEIF,ELSE,ENDIF
流程控制伪指令:
.WHILE,ENDW,REPEAT,UNTIL
.REPEAT,UNTILCXZ,BREAK,CONTINUE
过程声明伪指令 PROTO:事先声明过程的结构
( 包括操作系统 API函数,高级语言的函数 )
过程名 PROTO [调用距离 ] [语言类型 ]
[,参数 ∶[ 类型 ]]...
过程调用伪指令 INVOKE:实现过程调用
INVOKE 过程名 [,参数,...]
微机原理与接口技术
·

4
版机械工业出版社
3,程序退出函数
Win32程序员参考手册
VOID ExitProcess(
UINT uExitCode // exit code for all threads
);
汇编语言声明
ExitProcess PROTO,:DWORD
汇编语言调用
invoke ExitProcess,0
将函数调用定义成宏
exit MACRO dwexitcode
invoke ExitProcess,dwexitcode
ENDM
宏调用
exit 0
微机原理与接口技术
·

4
版机械工业出版社
4.4.2 控制台应用程序
Windows应用程序开始运行创建控制台 ( Console) 窗口或创建图形界面窗口
32位 Windows控制台程序像增强版的 MS-DOS程序使用 标准控制台标准输入设备 ( 键盘 )
标准输出设备 ( 显示器 )
32位控制台程序运行在保护方式通过 API使用 Windows的动态链接库函数微机原理与接口技术
·

4
版机械工业出版社
1,处理器识别指令 CPUID
返回处理器特征信息的指令
当 EAX= 0时执行 CPUID指令
EAX返回 CPUID指令中能够赋给 EAX的最大值
EBX,EDX和 ECX返回生产厂商的标识串
Genuine Intel
利用这个厂商标识串,确认是 Intel公司处理器
当 EAX= 1或 2等值时执行 CPUID指令返回处理器更详细的识别信息例如处理器型号,支持的指令集等微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-20〕 处理器识别程序- 1
.686
.model flat,stdcall
option casemap:none
includelib kernel32.lib
ExitProcess proto,:DWORD
GetStdHandle proto,:DWORD
WriteConsoleA \
proto,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WriteConsole equ <WriteConsoleA>
STD_OUTPUT_HANDLE = -11
.data
outhandle dword?
outbuffer byte 'The processor vendor ID is '
byte 12 dup(0)
outbufsize = sizeof outbuffer
outsize dword?
控制台句柄控制台输出微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-20〕 处理器识别程序- 2
.code
start,mov eax,0
cpuid ; 执行处理器识别指令
mov dword ptr outbuffer+outbufsize-12,ebx
mov dword ptr outbuffer+outbufsize-8,edx
mov dword ptr outbuffer+outbufsize-4,ecx; 获得输出句柄
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov outhandle,eax; 显示信息
invoke WriteConsole,outhandle,\
addr outbuffer,outbufsize,addr outsize,0; 退出
invoke ExitProcess,0
end start The processor vendor ID is GenuineIntel
运行结果微机原理与接口技术
·

4
版机械工业出版社
2,控制台句柄
句柄是一个 32位无符号整数用来唯一确定一个对象例如某个输入设备,输出设备或者一个图形
标准输入句柄
STD_INPUT_HANDLE = -10
标准输出句柄
STD_OUTPUT_HANDLE = -11
标准错误句柄
STD_ERROR_HANDLE = -12
GetStdHandle函数获取控制台输入或输出的句柄实例用于控制台程序的输入输出操作返回微机原理与接口技术
·

4
版机械工业出版社
3,控制台输出函数
显示器输出 API函数 WriteConsole
将一个字符串输出到屏幕上支持标准的 ASCII控制字符,例如回车,换行等
Win32 API中可以使用两种字符集
8位 ASCII字符集,函数名以字母 A结尾
16位 Unicode字符集,函数名以字母 W结尾
WriteConsole参数第一个:控制台输出句柄实例第二个:指向字符串的指针,即缓冲区地址第三个:指明字符串长度,是一个 32位整数第四个:指向一个整数变量,返回实际输出的字符数第五个:保留,设置为 0
返回微机原理与接口技术
·

4
版机械工业出版社
4,控制台输入函数
键盘输入 API函数 ReadConsole
将键盘输入的文本保存到一个缓冲区第一个:控制台输入句柄实例第二个:输入缓冲区指针第三个:要读取字符的最大数量第四个:实际输入字符数量的指针第五个:未使用,设置为 0
调用 ReadConsole函数时系统等待用户输入,并回车确认
( 例如用户输入了 3个字符,依次是 123)
第 4个参数的变量保存用户输入字符个数再加 2的结果
( 例如本例是 5)
( 内容用十六进制数表达依次是 31 32 33 0D 0A)
定义输入缓冲区要多留两个字节微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-21〕 信息输入输出程序- 1
.686
.model flat,stdcall
option casemap:none
includelib kernel32.lib
ExitProcess proto,:DWORD
exit MACRO dwexitcode
invoke ExitProcess,dwexitcode
ENDM
GetStdHandle proto,:DWORD
WriteConsoleA proto,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
WriteConsole equ <WriteConsoleA>
ReadConsoleA proto,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ReadConsole equ <ReadConsoleA>
STD_INPUT_HANDLE = -10
STD_OUTPUT_HANDLE = -11
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-21〕 信息输入输出程序- 2
.data
msg1 byte 'Please enter your name,',0
msg2 byte 'Welcome ',0
nbuf byte 80 dup(0)
msg3 byte ' to Win32 Console!',0
_outsize dword?
_outhandle dword?
_insize dword?
_inbuffer byte 255 dup(0); 设置输入缓冲区最大 255个字符微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-21〕 信息输入输出程序- 3
.code
start:
mov eax,offset msg1 ; 提示输入
call dispmsg
mov eax,offset nbuf ; 输入信息
call readmsg
mov eax,offset msg2
call dispmsg
mov eax,offset nbuf ; 显示输入信息
call dispmsg
mov eax,offset msg3
call dispmsg
exit 0
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-21〕 信息输入输出程序- 4
dispmsg proc ; 字符串显示子程序
push eax ; 入口参数,EAX=字符串地址
push ebx
push ecx
push edx
push eax ; 保存入口参数,即字符串地址
invoke GetStdHandle,STD_OUTPUT_HANDLE
mov _outhandle,eax
pop ebx ; EBX=字符串地址
xor ecx,ecx ; 计算字符串长度
dispm1,mov al,[ebx+ecx]
test al,al
jz dispm2
inc ecx
jmp dispm1
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-21〕 信息输入输出程序- 5
dispm2:
invoke WriteConsole,_outhandle,\
ebx,ecx,addr _outsize,0
pop edx
pop ecx
pop ebx
pop eax
ret
dispmsg endp
readmsg proc ; 字符串输入子程序
push ebx ; 入口参数,EAX=缓冲区地址
push ecx
push edx
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-21〕 信息输入输出程序- 6
push eax ; 保护输入的缓冲区地址参数
invoke GetStdHandle,STD_INPUT_HANDLE
invoke ReadConsole,\
eax,addr _inbuffer,255,addr _insize,0
sub _insize,2
xor ecx,ecx
pop ebx ; 获得缓冲区地址
readm1,mov al,_inbuffer[ecx]
mov [ebx+ecx],al; 将输入的字符串复制到用户缓冲区
inc ecx
cmp ecx,_insize
jb readm1
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-21〕 信息输入输出程序- 7
mov byte ptr [ebx+ecx],0; 最后填入结尾字符 0
mov eax,ecx
pop edx
pop ecx
pop ebx
ret
readmsg endp
end start
Please enter your name,Jerry
Welcome Jerry to Win32 Console!
运行结果微机原理与接口技术
·

4
版机械工业出版社
4.4.3 图形窗口应用程序
消息窗口是常见的 Windows图形窗口显示形式使用 MessageBox函数
Win32程序员参考手册的定义
int MessageBox(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
);
hWnd:父窗口的句柄
lpText:要显示字符串的地址指针,字符串的首地址
lpCaption:消息窗标题的地址指针
uType:指明该消息窗的类型微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-22〕 消息窗口程序- 1
.686
.model flat,stdcall
option casemap:none
includelib kernel32.lib
includelib user32.lib
ExitProcess proto,:DWORD
MessageBoxA PROTO,DWORD,:DWORD,:DWORD,:DWORD
MessageBox equ <MessageBoxA>
NULL equ 0
MB_OK equ 0
.data
szCaption byte '消息窗口 ',0
outbuffer byte '本机的处理器是 ',12 dup(0),0
outbufsize = sizeof outbuffer-1
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-22〕 消息窗口程序- 2
.code
start,mov eax,0
cpuid ; 获得显示器信息
mov dword ptr outbuffer+outbufsize-12,ebx
mov dword ptr outbuffer+outbufsize-8,edx
mov dword ptr outbuffer+outbufsize-4,ecx
invoke MessageBox,\
NULL,addr outbuffer,addr szCaption,MB_OK
invoke ExitProcess,NULL
end start
操作演示连接时应该使用参数
/subsystem:windows
微机原理与接口技术
·

4
版机械工业出版社
4.5 与 C++语言的混合编程
软件开发通常采用高级语言,以提高开发效率
某些部分需要利用汇编语言,以提高程序的运行效率,因为汇编语言的优点:开发的程序占用存储空间小,运行速度快等汇编语言的缺点:与机器密切相关,移植性差,编程烦琐,对汇编语言程序员要求较高
混合编程:汇编语言与高级语言,或高级语言间,
通过相互调用,参数传递,共享数据结构和数据信息而形成程序的过程
汇编语言与 C和 C++语言的混合编程嵌入汇编模块连接 MASM 6.15和 Visual C++ 6.0
微机原理与接口技术
·

4
版机械工业出版社
4.5.1 嵌入汇编
嵌入汇编
=内嵌汇编=内联汇编=行内 ( in-line) 汇编直接在 C和 C++语言的源程序中插入汇编语言指令
使用,_ _asm” 关键字指示嵌入汇编
Visual C++ 6.0支持通用整数和浮点指令集,以及 MMX指令集的嵌入汇编提供 _emit伪指令扩展不能支持的指令可以使用 C++的数据类型和数据对象可以使用 MASM的表达式和 MASM的注释风格不可以使用 MASM的绝大多数伪指令和宏汇编方法需要注意有些具体规定微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-23〕 嵌入汇编计算数组平均值函数- 1
#include <iostream.h>
#define COUNT 10
long mean(long d[],long num);
int main()
{
long array[COUNT] = {675,354,-34,198,267,0,9,
2371,-67,4257};
cout<<"The mean is \t"<<mean(array,COUNT)<<endl;
return 0;
}
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-23〕 嵌入汇编计算数组平均值函数- 2
long mean(long d[],long num) {
long temp; // 定义局部变量,用于返回值
_ _asm { // 嵌入式汇编代码部分
mov ebx,d ; EBX=数组地址
mov ecx,num ; ECX=数据个数
xor eax,eax ; EAX保存和值
xor edx,edx ; EDX=指向数组元素
mean1,add eax,[ebx+edx*4] ; 求和
add edx,1 ; 指向下一个数据
cmp edx,ecx ; 比较个数
jb mean1 ; 循环
cdq ; 将累加和 EAX符号扩展到 EDX
idiv ecx ; 有符号数除法,EAX=平均值
mov temp,eax }
return(temp); }
操作演示嵌入的汇编代码微机原理与接口技术
·

4
版机械工业出版社
4.5.2 模块连接
各种语言的程序分别编写
利用各自的开发环境编译形成 OBJ模块文件
将它们连接在一起,生成可执行文件
为了保证正确连接采用一致的调用规范声明共用函数和变量正确传递入口参数和返回参数使用 MASM的扩展过程定义微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-24〕 模块连接计算数组平均值函数- 1
#include <iostream.h>
#define COUNT 10
extern "C" { long mean(long d[],long num); }
int main()
{
long array[COUNT] = {675,354,-34,198,267,0,9,
2371,-67,4257};
cout<<"The mean is \t"<<mean(array,COUNT)<<endl;
return 0;
}
微机原理与接口技术
·

4
版机械工业出版社
〔 例 4-24〕 模块连接计算数组平均值函数- 2
.686
.model flat,c
mean proto d:ptr dword,num:dword ; 过程声明
.code
mean proc USES ebx ecx edx,d:ptr dword,num:dword; 过程定义
mov ebx,d ; EBX=数组地址
mov ecx,num ; ECX=数据个数
......
ret
mean endp
end
汇编模块操作演示
理解目标地址的转移范围和寻址方式
掌握控制转移指令处理器指令,JMP,Jcc,LOOP,JECXZ,CALL,RET
伪指令,PROC/ENDP,MACRO/ENDM,INCLUDE,INCLUDELIB
掌握各种程序结构及其编程方法单分支,双分支计数控制循环,条件控制循环子程序,子程序模块和子程序库,宏,文件包含
熟悉 Windows控制台和窗口应用程序的编程
熟悉嵌入汇编和模块连接的混合编程方法
熟悉常见编程问题数组运算,大小写转换,奇偶校验字符或数据个数统计,求最小值,最大值,字符删除二进制,十进制,十六进制数据相互转换二进制,十进制,十六进制数据的键盘输入和显示输出教学要求第 4章 汇编语言程序设计钱晓捷,微机原理与接口技术 ·第 4版 —— 基于 IA-32处理器和 32位汇编语言第 4章 习题
4.1 简答题 ( 1,2,3,4,7)
4.2 判断题 ( 2,3,4,6,8)
4.3 填空题 ( 2,3,5,7,9)
4.6 4.8 4.11 4.12 4.13 4.18
4.21 4.22 4.25 4.29 4.33