




已阅读5页,还剩60页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第4章汇编语言程序设计 本章重点 掌握汇编语言程序的规范格式掌握汇编语言程序设计的基本方法 顺序程序设计 循环程序设计 选择程序设计 子程序设计了解汇编语言与高级语言的接口 汇编语言的特点8086系统常用的汇编语言称为ASM 86 汇编语言的有如下的特点 1 汇编语言可以让我们从根本上了解计算机的工作原理 清晰的跟踪计算机的工作过程 2 计算机系统中 某些功能程序仍然用汇编语言来实现 比如机器自检 输入输出驱动程序 3 汇编语言书写的程序目标代码占用的内存空间少 执行速度快 效率高 实时性强 4 汇编语言可以直接调用系统中断 方便用户使用资源 4 1汇编语言设计概述 汇编语言的编译过程1 用文本编辑器编写符合汇编格式的程序 并将文件的扩展名命名为 ASM 该文件称为汇编源程序 2 利用汇编程序 MASM EXE 将汇编源程序翻译成计算机可以识别和运行的扩展名为 OBJ二进制目标程序 3 利用链接程序 LINK EXE 将目标文件进行地址重定位 目标程序组合等过程 产生用户可以执行的扩展名为 EXE的可运行程序 汇编语言语句类型指令性语句一条指令性语句就是一条8086的指令 例如ADDAL BL和MOVCX 1000 每一条指令性语句都会在汇编过程中产生相应的目标代码 指示性语句指示性语句又称为伪指令 例如SEGMENT和ABCDB50H 伪指令用来为汇编程序提供某些信息 让汇编程序在汇编的过程中执行特定功能的信息 比如规定一个数据段从哪里开始到哪里结束等 每一条伪指令在汇编的过程中都不会产生相应的目标代码 指令性语句的格式如下 指令助记符目标操作数START MOVAX 1090H 将16进制数1090H送入AXINCBX 指示性语句的格式如下 伪指令助记符CRDBODH 在字节单元CR处存放数据0DHORG200H 目标程序的偏移量DATASEGMENT 数据段开始 指令性语句和指示性语句的最大区别就是指示性语句在标识符和伪指令助记符没有冒号 汇编语句语句格式 段定义伪指令SEGMENT ENDS ASSUME伪指令SEGMENT和ENDS总是成对出现 SEGMENT用来定义段开始 ENDS是来定义段结束 这一段伪指令可以将源程序分为几个段 通常为数据段 堆栈段和代码段 格式为 段名SEGMENT 段内容 段名ENDS伪指令ASSUME告诉汇编程序 哪一个段是数据段 哪一个段是堆栈段 哪一个段是代码段 格式为 ASSUME段寄存器 段名源程序结束伪指令END 4 2汇编语言程序结构 一个标准汇编语言源程序结构如下 数据段名SEGMENT 数据段内容 数据段名ENDS堆栈段名SEGMENT 堆栈段内容 堆栈段名ENDS代码段名SEGMENTASSUMECS 代码段名 DS 数据段名 SS 堆栈段名 代码段内容 代码段名ENDSEND 注意 各个段的名称可以任意起 一般把数据段的段名记做DATA 堆栈段的段名记做STACK 代码段的段名记做CODE 规范程序示例 CODESEGMENT 定义段ASSUMECS CODE 把上面定义段的段基址放入CSMOVCX 100H 装入循环次数MOVDL 0 装入第一个ASCII码NEXT MOVAH 02INT21HINCDL 每次将数据寄存器DL内的数值加1LOOPNEXT 执行一次 CX减1 直到CX为0 MOVAH 4CH 终止当前程序并返回调用程序INT21H 返回DOSCODEENDS 段结束END 汇编程序结束 编译工具MASM的使用 MASM是专门为汇编语言设计的一种集编译 链接为一体的工具 它是利用文本编辑器 EDIT等 将汇编指令按照规范格式建成一个独立且扩展名为 ASM的汇编程序 称源程序 编译程序MASM将输入的ASM文件 编译成 OBJ文件 称为目标程序 OBJ文件仅包含有关程序各部分要载入何处及如何与其他程序合并的信息 无法直接载入内存执行 链接程序LINK则可将OBJ文件转换成可载入内存执行的EXE文件 利用MASM编译 链接汇编程序的步骤如下 1 用EDIT编辑一个扩张名为ASM的源程序文件 例如 smile asm 2 DOS窗口的命令提示符下输入 MASMSMILE 不用打入附加名 ASM 50162 403867Bytessymbolspacefree0WarningErrors 警告错误 表示编译器对某些语句不理解 通常是输入错误 0SevereErrors 严重错误 会造成程序无法执行 通常是语法结构错误 如果没有一个错误存在 即可生成OBJ文件 3 DOS窗口的命令提示符下输入 LINKSMILE 不用附加名OBJLINK warningL4021 nostacksegment 由于COM文件不使用堆栈段 所以错误信息并不 nostacksegment 影响程序正常执行 DEBUG和MASM的区别DEBUG是调试器 它的主要用途在于除错 能够观察每条汇编语句运行后的结果 方便的修正汇编程序中的错误 DEBUG中必须使用16进制的数 MASM是一种编译器 它能将汇编源程序进行编译 链接形成可执行文件 但汇编程序必须使用规范书写方式 源程序中除了指令性语句 还必须加入许多与指令语句无关的指示性语句 以供编译器识别 MASM中的数据默认为10进制 除了MASM外 还有TASM等工具软件也能对规范格式的汇编语言进行编译 段定义伪指令SEGMENT ENDS ASSUME和ORG 1 伪指令SEGMENT和ENDS总是成对出现 SEGMENT用来定义段开始 ENDS是来定义段结束 段名是合法的标识符 伪指令SEGMENT的参数有定位类型 组合类型和类别 格式为 段名SEGMENT 定位类型 组合类型 类别 段名ENDS定位类型 指定逻辑段在主存储器中的边界BYTE段基址为为任何地址 段间无空隙 xxxxxxxxB WORD段基址为下一个可用的偶数地址 xxxxxxx0B PARA段基址为下一个可用的节地址 xxxx0000B PAGE段基址为下一个可用的页地址 00000000B 默认的定位类型是PARA 组合类型 指定多个逻辑段之间的关系NONE本段与其他段没有逻辑关系 不与其他段合并 每段都有自己的段地址 PUBLIC连接程序把本段与所有同名同类型的其他段相邻地连接在一起 然后为所有这些段指定一个共同的段地址 也就是合成一个物理段 STACK仅用于堆栈段 连接程序将所有STACK段进行合并连接成一个物理段 系统初始化SS和SP COMMON连接程序把本段与所有同名同类型的其他段指定相同的段基址 即共享存储空间 MEMORY连接程序把本段定位在所有同名同类型的其他段后面 即最高的地址空间 默认的组合类型是NONE 2 伪指令ASSUME告诉汇编程序 哪一个段是数据段 哪一个段是堆栈段 哪一个段是代码段 格式为 ASSUME段寄存器 段名除CS的值可以自动装入外 其他各段的实际值还要用MOV指令来赋值 MOVAX DATAMOVDS AX 将数据段DATA的段基址送DSMOVAX STACKMOVSS AX 将堆栈段STACK的段基址送SSMOVSP TOP 堆栈指针指向栈顶 类别 类别必须用单引号括起来 连接程序所有程序中类别相同的段放在一个连续的存储空间里组合成一个物理段 STACKSEGMENTPARASTACK STACK 段名定位组合类型类别 DATASEGMENT数据段内容DATAENDSSTACKSEGMENT堆栈段内容STACKENDSCODESEGMENTASSUMECS CODE DS DATA SS STACKSTART MOVAX DATAMOVDS AX 初始化DSMOVAX STCAKMOVSS AX 初始化SSMOVSP TOP 初始化SP MOVAH 4CHINT21H 程序正常结束CODEENDSENDSTART 过程定义伪指令PROC ENDP过程就是完成某个特定功能的子程序 应用伪指令PROC和ENDP定义过程的格式如下 过程名PROC NEAR FAR 过程名ENDP 1 过程名 子程序名 为符合语法的标识符 2 属性 NEAR属性 段内近调用 的过程只能被相同代码段的其他程序调用 FAR属性 段间远调用 的过程可以被相同或不同代码段的程序调用 NEAR属性是默认值 3 调用过程 CALL过程名 4 过程返回 RET 程序结束伪指令END格式是 END 标识符 标识符是可选项 它是程序起始地址的标识符 CODESEGMENT 定义段ASSUMECS CODE 把CODE段的段基址放入CSSTART MOVDL 1MOVAH 02INT21HMOVAH 4CH 终止当前程序并返回调用程序INT21H 返回DOSCODEENDS 段结束ENDSTART DATASEGMENT 数据段开始ARRAYDB3 12 45 21 97 56 8 存放7各数字MAXNUMDB MAXNUM单元存放最大数DATAENDS 数据段结束CODESEGMENT 代码段开始ASSUMECS CODE DS DATASTART MOVAX DATAMOVDS AX 数据段寄存器赋值MOVBX OFFSETARRAY 取数组的偏移量送BXMOVCX 6 比较的次数送CXMOVAL BX 取第一个数LABLE INCBX 偏移量加1 指向下一个数CMPAL BX 比较AL和第N 1个数JNBNEXT 不低于则转入NEXTMOVAL BX 否则将大数送ALNEXT LOOPLABLE 继续下一次比较 直到CX为0MOVMAXNUM AL 最大数送MAXNUM单元MOVDL ALMOVAH 02INT21H 显示输出最大数97MOVAH 4CHINT21H 程序正常结束CODEENDS 代码段结束ENDSTART 汇编程序结束 常量常量就是指令中出现的固定值 比如MOVAX 90 1 数字常量如果一个常数后面加字母B来表示二进制数 如果一个常数后面加字母D 可不加 表示十进制数 如果一个常数后面加字母H来表示十六进制数 一个16进制数以字母A F开头 前面必须加一个0 如0A59H2 字符常量单引号引出的字符表示字符常量 如 c 表示字符c 单引号引出的多个字符序列称为字符串常量 如 ABC 注意 一个用引号引出的字符串也代表常数 如带引号的字符串 ABC 等效于它们对应的ASCII的常数64 65 66 4 3汇编语言的语法 变量变量是存放数据的存储器单元的符号地址 在程序运行过程中其值可以变化 伪指令DB DW DD用来定义变量变量的属性1 段基址 SEG 变量所在段的起始地址2 偏移量 OFFSET 变量所在地址与段基址的相对距离3 类型 TYPE 变量指示的存储区中每个数据所占的内存单元的字节数 可以是字节 1字节 字 2字节 双字 4字节 注意 1 变量定义后可以使用 在指令中必须与操作数类型一致2 变量的偏移地址仅仅对应其所代表的数据区的首地址 如果这个数据区有多个数据项 对后面的数据项操作时必须改变地址值 定义变量伪指令DB DW DD该组伪指令用来给出程序中所用到的数据 字符串以及存储单元 DB用来定义字节 DW用来定义字 DD用来定义双字 变量定义的格式为 变量 伪指令参数1 参数2 例如 CRDB10HLFDB0BH 64HRPDWFBFFH 3CH 1 操作数 用来保留存储空间 但不存入数据 ABCDB0BH 06H LPIDW 54H ABC LPI 2 操作数还可以用复制操作符DUP来缩写BUFFERDB9DUP ABCDB0 1 3DUP 3 操作数可以是字符串STRINGDB HELLO STRING 汇编的表达式和运算符 表达式是常数 寄存器 标识符与一些运算符组合的序列 分数字表达式和地址表达式两种 汇编时按一定的优先规则对表达式进行计算后可得到一个数值或一个地址 算术运算符逻辑运算符关系运算符分析运算符综合运算符 算术运算符 有 MOD 算术运算符可以用于数字表达式 例如 MOVAL 2 7汇编后为MOVAL 0E算术运算符也可以用于地址表达式 对地址运算的结果应有明确的物理意义 例两个地址的乘或除无意义 而加或减则可以 例如 BUFDW1 2 3 4 5 6 7 8MAXDW MOVCX BUF MAX 2汇编后为MOVCX 8 逻辑运算符 逻辑运算符有AND OR XOR和NOT 它们只能用于数字表达式中 例如 MOVCL 36HAND0FH经汇编后 MOVCL 06H 这些逻辑运算符也是8086 8088的指令助记符 会不会造成混乱呢 不会的 前者在汇编时进行 而后者在指令执行时进行的 例如 ANDDX 36HAND0FH后一个逻辑运算符AND在汇编时进行 汇编后得到表达式的值为06H 运行时执行前一个指令助记符AND 将 DX 与06H相与 结果在DX中 关系运算符 共有6个 它们为 EQ 相等 NE 不等 LT 小于 GT 大于 LE 小于或等于 GE 大于或等于 关系运算符的两个操作数必须都是数字或者是同一段内的两个存储器地址 关系为真 结果为0FFFFH 关系为假 结果为0例如 MOVBX PORTGE5若PORT的值大于等于5 则汇编后为 MOVBX 0FFFFH若PORT的值小于5 则汇编后为 MOVBX 0 分析运算符 分析运算符的OFFSET SEG可以把一个存储单元的地址分解为段基址和偏移量 1 运算符OFFSET用来取地址的偏移量 2 运算符SEG取存储单元的段地址 例如在规范程序中有定义 ABCDB11H 则执行 MOVDX OFFSETABC此语句将ABC处的偏移量0150H送DX 则执行 MOVDX SEGABC此语句将ABC处的段地址1EFFH送DX 3 分析运算符的TYPE SIZE及LENGTH可以把存储器一些特征作为数值送回 TYPE运算符用来取存储器的单元类型 各单元类型对应值如下 存储器单元类型对应值DB 字节 1DW 字 2DD 双字 4 LENGTH运算符用来计算一个存储区的单元的数目 SIZE运算符用来计算一个存储区的字节总数 若BUFFER存储区是用如下伪指令定义的 BUFFERDW100DUP 则TYPEBUFFER等于2 LENGTHBUFFER等于100 SIZEBUFFER等于200 合成运算符PTR 用来对存储单元规定类型 通常和BYTE WORD和DWORD等连起来使用 考虑下面的语句 MOV 1000 0 类型不定 MOVBYTEPTR 1000 0 1000字节单元清零MOVWORDPTR 1000 0 1000开始的字单元清零 1000字节单元清零 1000开始的字单元清零 INCWORDPTR SI SI所指内存1个字自增1JMPDWORDPTR SI 段地址CS在SI SI 1中 偏移量IP在SI 2 SI 3中 标号赋值伪指令EQU为了便于阅读和修改 汇编程序常常使用标识符代表数据或者寄存器 必须在源程序前用EQU伪指令对标识符赋值 格式为 标识符EQU操作数例如 CONSTANTEQU100COUNTEQUCX在一个程序中不能用EQU对一个标识符多次重复定义 标号解除伪指令PURGE此伪指令用来解除用EQU对某一个标识符的赋值例如 PURGECONSTANT等号伪指令 与EQU功能一样 但那是可以多次重复定义同一标识符 汇编的常用的伪指令 定位伪指令ORG指定数据段或者代码段的偏移地址 DATASEGMENTORG0200HBUFDB10DUP 变量BUF的在数据段的偏移地址DATAENDS 是0200H 省略为0000HCODESEGMENTASSUMECS DCODE DS DATAORG1000H 首条指令在代码段的偏移地址MOVAX DATA 是1000H 省略为0100HMOVDS AX CODEENDSEND 地址计数器 汇编语言中 每一个段都有一个地址计数器 指示当前指令或者数据的在段内的偏移量 某数据段定义如下 DATASEGMENTORG1000HBUFDW1 2 3 2 1234HCOUNTEQU BUF 2NUMDW5ABBH BUFDATAENDS汇编后内存的分配如右所示 概述 1 SEGMENT和ENDS前面的标识符为各个段的名称 可以任意起名 一般把数据段的段名记做DATA 堆栈段的段名记做STACK 代码段的段名记做CODE 2 ASSUME告诉汇编程序 哪一个段是数据段 哪一个段是堆栈段 哪一个段是代码段 除CS的值可以自动装入外 其他各段的实际值还要用MOV指令来赋值 3 指令性语句的标识符后面要有冒号 如标识符NEXT 指示性语句的标识符后面没有冒号 如标识符DATA CODE 4 每一个汇编程序都要调用21H中断的4C功能子程序让程序正常结束 否则运行出错 4 4汇编程序设计概述 例 要求完成两个32位的数据相加运算DATASEGMENTXDD10008423HYDD20007F00HZDD DATAENDSCODESEGMENTASSUMECS CODE DS DATASTART MOVAX DATAMOVDS AX 初始化DS 顺序程序设计 顺序程序完全按指令书写的前后顺序执行每一条指令 是最基本 最常见的程序结构 MOVSI OFFSETXMOVAX SI 取第1个数的低16位送AXMOVDI OFFSETYADDAX DI 低16位相加MOVBX OFFSETZMOV BX AX 送低16位和MOVAX SI 2 取第1个数的高16位送AXADCAX DI 2 高16位连同进位标志相加MOV BX 2 AX 送高16位和MOVAH 4CHINT21H 程序结束CODEENDSENDSTART 例 编写程序 判别键盘上输入的字符 若是0 9字符 则显示之 若为a z字符 均显示 c 若是回车字符 0DH 则结束程序 若为其它字符则不显示 分支程序设计 CODESEGMENTASSUMECS CODESTART MOVAH 1INT21HCMPAL 0DHJZDONECMPAL 0 JBSTARTCMPAL 9 JACHRDNMOVDL ALMOVAH 2INT21HJMPSTART CHRDN CMPAL a JBSTARTCMPAL z JASTARTMOVDL C MOVAH 2INT21HJMPSTARTDONE MOVAH 4CHINT21HCODEENDSEND 循环程序设计 循环结束的控制可以用循环次数 还可以用特定条件等 1 计数控制循环 LOOP LOOPZ LOOPNZ2 条件控制循环 JCC 例 计算SUM i i 1 100 COUNTEQUCXDATASEGMENT 数据段开始SUMDW DATAENDS 数据段结束CODESEGMENT 代码段开始ASSUMECS CODE DS DATAORG200H 代码段偏移量为0200H处存放代码MOVAX DATAMOVDS AX 数据段寄存器赋值XORAX AX 累加器AX清零MOVCOUNT 100 置循环次数 CX 100NEXT ADDAX CX 求累加和LOOPNEXTMOVSUM AX 将累加和送指定单元MOVAH 4CHINT21H 4C号功能调用 终止当前程序并返回调用程序CODEENDS 代码段结束END 汇编程序结束 例 以10进制向屏幕输出BX中的16位无符号数分析 将BX的数据除以10 余数保存 商继续除以10 余数保存 直到商为0 余数的倒序即为待显示的数字 将待显示的数字加30H变成对应数字的ASCII码 调用21H中断的2号子程序向屏幕输出 程序清单 STACKSEGMENTSTAKDB64DUP 堆栈段大小是64个字节TOPEQULENGTHSTAK 标识符STACKENDSCODESEGMENTASSUMECS CODE SS STACK 绑定各个段与段寄存器START MOVAX STACKMOVSS AX 初始化SSMOVSP TOP 初始化SP MOVSI 10 SI中是除数XORCX CXMOVBX 174 待输出的数据MOVAX BXNEXT MOVDX 0 DX存放余数 清零DIVSI AX中的数除以10PUSHDX 余数入栈INCCXCMPAX 0 商为0则完成转换JNZNEXTOUTP POPDX 余数出栈ADDDL 30H 转化数字为对应的ASCIIMOVAH 2INT21HLOOPOUTPMOVAH 4ChINT21H 结束程序CODEENDSENDSTART 注意 堆栈段定义建议如下 则SS和SP的初始化由系统完成 STACKSEGMENTSTACK STACK 子程序 也称为过程 是功能相对独立的一段代码 每一个子程序都有唯一的合法标识符作为子程序名 它也是子程序入口地址的符号表示 1 子程序调用 CALL子程序名 寄存器 内存单元主程序可以采用子程序名调用对应的子程序 目标地址就在CALL指令中 称为直接调用 目标地址也可以在寄存器或者存储单元中 称为间接调用 子程序如果在当前代码段中 称为段内调用 子程序也可以不在当前代码段中 称为段间调用 2 子程序返回 RET子程序的出口地址是返回指令RET 可以带1个立即数作为参数 必须是子程序的最后一条指令 有段内返回和段间返回两种 子程序设计 3 保护断点 为了保证子程序结束后 被中断的主程序返回断点处继续执行 必须在执行CALL指令时对返回地址推入堆栈进行保存 段内调用保存IP 段间调用保存CS和IP 段内调用 SP SP 2 SS SP IP段间调用 SP SP 2 SS SP CSSP SP 2 SS SP IP4 恢复断点 在执行RET指令时 将CALL指令推入堆栈的返回地址恢复 段内调用恢复IP 段间调用恢复CS和IP 段内返回 IP SS SP SP SP 2段间返回 IP SS SP SP SP 2CS SS SP SP SP 2注意 保护断点的入栈过程和恢复断点的出栈过程是系统自动完成的 不需要程序员干预 5 子程序格式 子程序以PROC开始 以ENDP结束 如果是段内调用 用默认值NEAR属性 段间调用 用FAR属性 过程名PROC NEAR FAR 过程名ENDP 6 保护现场 子程序运行过程时 会使用CPU中的某些通用寄存器 为了在子程序结束之后 主程序恢复调用前的状态继续运行 必须在子程序执行之前 把子程序将要使用的寄存器的数据压入堆栈加以保护 7 恢复现场 将原来推入堆栈的通用寄存器的数据弹出 恢复主程序调用之前程序的运行状态 注意 保护现场和恢复现场是子程序完成的 根据子程序的需要将相应的寄存器加以保护 子程序名PROCNEAR 该子程序用于段内调用PUSHAX 保护寄存器 顺序压入堆栈PUSHBXPUSHCX 过程体POPCX 恢复寄存器 逆序弹出堆栈POPBXPOPAXRET 过程返回子程序名ENDP 过程结束 8 子程序基本内容 子程序除了固定格式外 一般还包括保护现场的PUSH指令和恢复现场的POP指令 子程序设计的一个关键问题就是堆栈内容和堆栈指针的变化情况 子程序的参数传递子程序设计的另一个关键问题是参数以及参数传递 参数的类型有两种 入口参数 主程序调用子程序时 提供给子程序运行的原始数据 可以是数据本身也可以是地址 出口参数 子程序执行结束时提供给主程序的结果 子程序的参数传递主要有以下三种方式 利用寄存器传递参数 将入口参数或出口参数放在规定的寄存器中 采用寄存器传递出口参数的寄存器不能保护 利用存储单元传递参数 将入口参数或者出口参数放在内存区域中 一般采用共享变量实现 利用堆栈传递参数 将入口参数或者出口参数推入堆栈 利用堆栈完成参数交换 必须注意堆栈内容和堆栈指针 利用寄存器传递参数由于CPU内部寄存器个数有限 该方式仅仅适用于传递参数不多的情况 例 编写一个子程序 该子程序的功能是将16位无符号数转换成10进制数向屏幕显示 子程序名 Display入口参数 BX出口参数 无子程序程序清单 DisplayPROCNEARPUSHAX 保护寄存器PUSHBXPUSHCXPUSHDXPUSHSIMOVSI 10 SI中是除数XORCX CXMOVAX BX 入口参数在BX中 NEXT1 MOVDX 0 DX存放余数 清零DIVSI AX中的数除以10PUSHDX 余数入栈INCCXCMPAX 0 商为0则完成转换JNZNEXT1OUTP POPDX 余数出栈ADDDL 30H 转化数字为对应的ASCIIMOVAH 2INT21HLOOPOUTPPOPSI 恢复寄存器POPDXPOPCXPOPBXPOPAXRET 子程序返回DisplayENDP 例 计算1 2 3 100 调用子程序Display显示结果 STACKSEGMENTSTACK STACK STAKDB64DUP 堆栈段大小是64个字节STACKENDSCODESEGMENTASSUMECS CODE SS STACKMAINPROC 主过程开始START MOVCX 100NEXT ADDAX CXLOOPNEXTMOVBX AX 置入口参数CALLDisplay 调用子程序MOVAH 4CHINT21HMAINENDP 主过程结束DisplayPROC 子过程开始 属性为NEAR DisplayENDP 子过程结束CODEENDSENDSTART 利用存储单元传递参数子程序和主程序使用同一个变量名存取数据就是利用共享存储单元进行参数传递 类似于C的全局变量 如果主程序还要利用原来的变量值 则需要保护和恢复利用共享变量传递参数 子程序的通用性较差 但特别适合在多个程序段间 尤其在不同的程序模块间传递数据例 利用子程序来实现数据块的移动 子程序名 MOVEDAT入口参数 字变量SCRADR存放源数据块首地址字变量DESADR存放目标数据块首地址字变量LEN存放数据块字节数出口参数 无 数据块传送的三种情况 1 对于数据块无重叠区的情况 可分别从首 末 地址开始传送 如 A 2 对有数据块有重叠区的情况 应分别对待 当源数据块首址小于目标块首址时 应从数据末址开始传数 如 B 当源数据块首址大于目标块首址时 应从数据首址开始传数 如 C DATASEGMENTBUF1DB100DUP BUF2DB100DUP SRCADRDW DSTADRDW LENDW DATAENDSCODESEGMENTASSUMECS CODE DS DATA ES DATAMAINPROCSTART MOVAX DATAMOVDS AXMOVES AXLEAAX BUF1MOVSRCADR AX 入口参数赋值LEAAX BUF2MOVDESADR AX 入口参数赋值MOVLEN 100 入口参数赋值CALLMOVEDAT 调用子程序MOVAH 4CHINT21HMAINENDP MOVEDATPROCPUSHSI 保护寄存器PUSHDIPUSHCXMOVSI SRCADR 源数据块首地址送SIMOVDI DESADR 目标数据块首地址送DIMOVCX LEN 传送长度送CXCLDCMPSI DI 比较源块和目标块首地址JADONE 小于则从首地址递增传送STD 大于则从末地址递减传送ADDSI CXDECSI 源串末地址ADDDI CXDECDI 目标串末地址DONE REPMOVSEPOPSI 恢复寄存器POPDIPOPCXRETMOVEDATENDPCODEENDSENDSTART 利用堆栈传递参数参数传递还可以通过堆栈这个临时存储区 主程序将入口参数压入堆栈 子程序从堆栈中取出参数 子程序将出口参数压入堆栈 主程序弹出堆栈取得它们 采用堆栈传递参数是程式化的 它是编译程序处理参数传递 以及汇编语言与高级语言混合编程时的常规方法 例 编写子程序求2个16位数据的和 子程序名 Addition入口参数 堆栈出口参数 AXSTACKSEGMENTSTACK STACK STAKDW50DUP 堆栈段大小是50个字STACKENDSDATASEGMENTDAT1DW100DAT2DW200SUMDW DATAENDS CODESEGMENTASSUMECS CODE DS DATA SS STACKMAINPROCSTART MOVAX DATAMOVDS AXMOVAX DAT1PUSHAX DAT1入栈MOVAX DAT2PUSHAX DAT2入栈CALLAddition 调用子程序MOVSUM AXMOVAH 4CHINT21HMAINENDPAdditionPROCPUSHBPMOVBP SP 得到栈顶地址MOVAX BP 4 取第二个数ADDAX BP 6 取第一个数和第二个数相加POPBPRET4 SP 4 丢掉堆栈无用参数AdditionENDPCODEENDSENDSTART 例 编写一个程序找出内存N个连续的字节 字或者双字 空间中存放的无符号数的最大值 程序清单 STACKSEGMENTSTACK STACK STAKDW50DUP 堆栈段大小是50个字STACKENDSDATASEGMENTARRAYDB3 12 45 21 97 56 8 存放7个数字MAXNUMDB 存放最大数DATAENDSCODESEGMENTASSUMECS CODE DS DATA SS STACKMAINPROCSTART MOVAX DATAMOVDS AX 数据段寄存器赋值XORAX AX 汇编程序设计举例 MOVBX OFFSETARRAY 取数组的偏移量送BXMOVCX 6 比较的次数送CXMOVAL BX 取第一个数LABLE INCBX 偏移量加1 指向下一个数CMPAL BX 比较AL和第N 1个数JNBNEXT 不低于则转入NEXTMOVAL BX 否则将大数送ALNEXT LOOPLABLE 继续下一次比较MOVMAXNUM AL 最大数送MAXNUM单元MOVBX AXCALLDisplay 调用显示子程序MOVAH 4CHINT21HMAINENDPDisplayPROC 显示子程序 DisplayENDPCODEENDSENDSTART 例 编写一个程序使内存5个连续的字节 字或者双字 空间中存放的无符号数按序排列存放 分析 冒泡法 将低地址字节空间中的数和其他4个字节空间的数分别4次两两比较 大则交换两个字节空间的数据 否则不交换 经过1趟比较之后最大的数交换至高字节地址空间 对于5个数据 只要经过四趟比较数据就会按序排列存放 利用BX寄存器存放比较的趟数 每次比较完1趟后BX的值减1 当BX的值为0时 比较结束 程序清单 STACKSEGMENTSTACK STACK STAKDW50DUP 堆栈段大小是50个字STACKENDSDATASEGMENTARRAYDB Z P S E M 存放5个数DATAENDSCODESEGMENTASSUMECS CODE DS DATA SS STACK 绑定各个段与段寄存器START MOVAX DATAMOVDS AX MOVBX 4 送大循环的次数 比较的趟数SORT MOVCX BX 送小循环的次数 每趟比较的次数MOVSI OFFSETARRAY 取数组的偏移量送SICOMP MOVAL SI 送数组中第n个数CMPAL SI 1 比较数组中第n个数和n 1个数JNALABLEXCHGAL SI 1 MOV SI AL 大于则交换两个数LABLE INCSI 指向下一个数LOOPCOMP 继续下
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年注册验船师资格考试(B级船舶检验专业法律法规)测试题及答案五
- 幼儿园师德师风工作总结汇报5篇
- 2025年注册验船师考试(C级船舶检验专业基础安全)冲刺试题及答案一
- 2025年国际旅行社导游岗位面试题及标准答案公布
- 2025年房地产销售招聘面试技巧与模拟题集答案
- 四川省资阳市安岳县石羊中学2026届化学高一上期末调研试题含解析
- 2025年青少年心理健康辅导培训课程试题及答案
- 2025年食盐储备库管理知识模拟考试题库
- 2025年初级软件工程师考试模拟题及答题技巧指导
- 2025年街道安全员实操面试题库大全
- 2025-2026学年高二上学期开学入学教育主题班会【课件】
- 北师大版八年级数学上册第一章 勾股定理 单元测试卷(含答案)
- 护工清洁护理培训
- 出租房屋安全管理办法
- 违法建筑用电管理办法
- 2025年党建知识竞赛题库及答案(完整版)
- 寺庙安全隐患排查台账内容
- 广西旅游发展集团有限公司招聘考试真题2024
- 烹饪高级技师论文
- 大模型备案-落实算法安全主体责任基本情况
- 会议摄影拍摄教学课件
评论
0/150
提交评论