1、汇编语言程序设计-朱明2第三章提问 MOV指令要求源操作数和目的操作数的尺寸必须相同,其功能为将源操作数的值复制到目的操作数中,但有两个源操作数要比目的操作数尺寸小的类似功能的指令是什么?其功能是什么?CF(进位标志位)的判断方法是什么?OF(溢出标志位)的判断方法是什么?SIZEOF操作符、LENGTHOF操作符和TYPE操作符分别返回什么值?三者之间有什么关系?PTR操作符是否会改变操作数的原有类型?保护模式下程序可以访问的最大虚拟内存范围是多少?是如何计算的?什么操作符可取得其段内偏移地址?汇编语言程序设计-朱明9间接寻址 通过间接操作数寻址访问数组 注意要访问的数组元素的大小arr2B
2、YTE 10h,20h,BYTE 30h,40hmov esi,OFFSET arr2mov al,esiincesimov al,esiincesimov al,esi假设此时esi=00040500esi=0004050110h20h30h40h00040500000405010004050200040503esi=00040502汇编语言程序设计-朱明10问题处理 加入间接寻址的方法.dataarr1DWORD 111h,222h,333h,444h,555hval1DWORD?.codemainPROCmoveax,TYPE arr1movval1,eaxmovecx,LENGTHOF
3、 arr1movesi,OFFSET arr1moveax,0L1:addeax,esiaddesi,val1LOOPL1exitmainENDPENDmain间接寻址使用ESI汇编语言程序设计-朱明11问题处理 对于整数数组求和问题的总结与思考 若使用操作数间接寻址则要保存数组的起始偏移地址至某个用于寻址的寄存器中 取得数组种元素的数目并送ECX作为计数器初始值 选择另外一个寄存器用于累加保存结果并将其清零 创建一个用于标示循环体的标号 在循环体中利用操作数间接寻址的方式进行累加操作 修改用于寻址的寄存器,使其指向数组的下一个元素 使用LOOP指令重复执行循环体内容汇编语言程序设计-朱明12
4、间接寻址 通过间接操作数进行寻址 通过间接操作数寻址时,寄存器中存放的是地址/偏移 通过变址操作数进行寻址 通过变址操作数寻址时,寄存器中不直接存放地址/偏移,而存放一个相对于地址/偏移的增量addesi,2moval,esimovesi,2moval,aar1esimoval,aar1+esi汇编语言程序设计-朱明13间接寻址 通过变址操作数寻址访问数组 注意要访问的数组元素的大小arr3BYTE 50h,60h,BYTE 70h,80hmov esi,0mov al,arr3+esiaddesi,1mov al,arr3+esiaddesi,1mov al,arr3+esiesi=050h
5、60h70h80h00040500000405010004050200040503假设arr3的存储为esi=1esi=2汇编语言程序设计-朱明14间接寻址 通过比例因子访问数组 其中的*并不是表示乘法,而是表示比例因子 IA-32处理器支持比例因子的计算方法来计算偏移地址 比例因子通常是数组元素的大小(1、2、4.),可以直接使用TYPE操作符获得元素的大小arr4WORD 11h,12h,13hmovesi,2movax,esi*2movax,esi*TYPE arr4汇编语言程序设计-朱明15间接寻址 间接寻址另一个应用字符串复制thi.datastr1BYTE“this is the
6、source string”,0str2BYTE(1).codemainPROCmovecx,(2)movesi,0L1:moval,str1esimov(3),al(4)LOOPL1exitmainENDPENDmainstr1str2(1)SIZEOF str1 DUP(?)(2)SIZEOF str1(3)str2esi(4)inc esi汇编语言程序设计-朱明16回顾与练习 关于循环的基本操作练习 编写一个可以实现计算从1开始到1000以内的任意自然数连续相加的汇编语言程序,占成绩10%1+.+MaxVal(MaxVal是一个程序中定义的变量)下次课上课之前发送至姓名_班级_学号,附件
7、形式发送代码 关于循环和间接寻址的一个练习 使用LOOP循环指令和间接寻址实现字符串的逆序复制.datastr1BYTE“this is the source string”,0str2BYTESIZEOF str1 DUP(?)汇编语言程序设计-朱明17thi回顾与练习关于循环和间接寻址的一个练习 使用LOOP循环指令和间接寻址实现字符串的逆序复制sstr1str2ing0gnisiht0ESIEDI汇编语言程序设计-朱明18过程的定义 在汇编语言中也有类似高级语言的subroutine机制,称为过程(procedure)过程的定义 过程定义以PROC伪指令开头,以ENDP伪指令结尾 过程定
8、义需要一个有效的标识符作为过程名 被调用过程内应该以RET指令结束,以完成返回;主过程(main)应该以exit结束sample PROC retsample ENDPmain PROC exitmain ENDP汇编语言程序设计-朱明19过程的定义 过程的写法与格式 前面要求的三个过程定义的基本要求 过程的书写在格式上的要求,包含程序的功能说明、需要使用的参数、返回的结果等方面的注释的内容,程序书写上正确的、适合阅读的缩进结构等;-SumOf PROC;Calaulates and returns the sum of three 32-bit integers.;Receives:EAX,
9、EBX,ECX;Return:EAX,saves the sum;-addeax,ebxaddeax,ecxretSumOf ENDP汇编语言程序设计-朱明20过程的调用 CALL指令指示处理器在新的内存地址执行指令call foo.retEIP004000800040002000400025004000250040002000400080EIP被压栈跳转汇编语言程序设计-朱明21过程的返回 RET指令从栈中弹出EIP,并按照EIP继续执行程序call foo.retEIP0040008000400020004000250040011000400025004000200040008000400
10、11000400025EIP被压栈跳转跳转弹栈为EIP汇编语言程序设计-朱明22 一个过程在返回之前又调用了其他过程会造成嵌套PA返回后地址过程的嵌套call PA.call PBretcall PCretretPA返回后地址PB返回后地址PB返回后地址PA返回后地址PC返回后地址PC返回后地址PB返回后地址PA返回后地址PB返回后地址PA返回后地址PA返回后地址PC返回后地址PB返回后地址PA返回后地址汇编语言程序设计-朱明23过程的参数传递 过程中常常需要参数的传递 如果我需要对数组中的N个数求和 每次都通过寄存器传递?要传递若干次 C语言里面怎么做到的?;-SumOf PROC;Cala
11、ulates and returns the sum of three 32-bit integers.;Receives:EAX,EBX,ECX;Return:EAX,saves the sum;-addeax,ebxaddeax,ecxretSumOf ENDP汇编语言程序设计-朱明24过程的参数传递 过程中常常需要参数的传递 例如可以传递一个数组偏移和一个元素的数量 数组偏移保存在ESI寄存器中 元素数量保存在ECX寄存器中ArraySum PROC;保护现场,压栈moveax,0;清除加法值L1:addeax,esi;执行加法操作addesi,TYPE DWORD;指向下一个整数loo
12、pL1;重复循环;恢复现场,弹栈ret;结果保存在EAX中ArraySum ENDP汇编语言程序设计-朱明25过程与堆栈 过程的现场保护实际上就是栈的压栈操作 过程的现场恢复实际上就是栈的弹栈操作 堆栈的操作原则(结构):LIFO 新入栈的数据保存在栈的顶端(小地址)PA返回后地址PA返回后地址PB返回后地址PB返回后地址PA返回后地址PC返回后地址PB返回后地址PA返回后地址PB返回后地址PA返回后地址PA返回后地址PC返回后地址PB返回后地址PA返回后地址汇编语言程序设计-朱明26过程与堆栈 堆栈结构与堆栈指针 压栈操作(CALL指令和PUSH指令)堆栈指针ESP始终指向一个有数据的地址/
13、偏移 堆栈指针ESP先修改自身的值(-4),然后再存入数据 IA-32处理器所管理的堆栈中的大地址作为栈底,小地址作为栈顶00000FF000000FF400000FF800000FFC0000000600001000压栈前ESP压栈00000FF000000FF400000FF8000000A500000FFC0000000600001000压栈后ESP汇编语言程序设计-朱明27过程与堆栈 堆栈结构和堆栈指针 弹栈操作(RET指令和POP指令)对于处理器来说,比堆栈指针地址小的堆栈数据是无效的 堆栈先弹出数据,再修改堆栈指针ESP的指(+4)堆栈的运行是由CPU内部的硬件直接完成的,一般不需
14、要用户修改ESP的值00000FF000000FF400000FF8000000A500000FFC0000000600001000弹栈前ESP弹栈00000FF000000FF400000FF800000FFC0000000600001000弹栈后ESP汇编语言程序设计-朱明28过程与堆栈 堆栈的几个重要用途 寄存器在多种用途的时候,堆栈可以作为临时区域方便的临时保存或恢复原有的值 CALL指令执行时,堆栈用于保存其返回地址 在进行过程调用时,可以通过堆栈传递参数 过程内部的局部变量在堆栈上运行,过程结束时放弃 与堆栈操作相关的指令 压栈:CALL、PUSH、PUSHFD、PUSHAD、PU
15、SHA 弹栈:RET、POP、POPFD、POPAD、POPA汇编语言程序设计-朱明29过程与堆栈 与堆栈操作相关的指令 PUSH reg/mem/imm,将寄存器的值或内存中的值或立即数压入堆栈 PUSHFD,将EFLAGS寄存器的值压入堆栈 PUSHAD,按照由先至后的顺序依次将EAX、ECX、EDX、EBX、ESP的原始值、EBP、ESI和EDI压入堆栈 PUSHA,与PUSHAD同样的顺序将16位寄存器的值压入堆栈 POP reg/mem,将栈顶的值弹出到寄存器或内存中 POPFD、POPAD和POPA分别与对应的PUSHFD、PUSHAD和PUSHA类似,执行弹栈操作,但顺序相反汇编
16、语言程序设计-朱明30回顾与练习 关于堆栈和间接寻址的一个练习使用对栈操作和间接寻址实现字符串的逆序复制.datastr1BYTE“this is the source string”,0str2BYTESIZEOF str1 DUP(?)thisstr10000006800000074sihstr1t压栈弹栈汇编语言程序设计-朱明31过程化程序设计 自上而下的程序设计方法 将大问题分解成为小问题处理 每一个过程都可以进行独立的测试且便于维护 过程之间有明显而简洁的依赖关系 每个过程都更容易解决细节的问题和处理代码的实现 过程化的程序设计以程序的过程作为基本单位 main过程(主过程)Dump
17、Regs过程(用于显示寄存器值的过程)整数求和问题 写一个程序,要求用户从键盘输入3个32位整数,保存在数组中,并计算数组内元素的和并显示在屏幕上汇编语言程序设计-朱明32过程化程序设计 自上而下的程序设计方法整数求和问题用户输入系统计算输出结果运行流程图代码结构图用户输入系统计算输出结果读键盘输入数据屏幕显示运算结果主体程序显示提示显示提示汇编语言程序设计-朱明33过程化程序设计 自上而下的程序设计方法整数求和问题主体伪代码main;清除屏幕的内容;用户输入数据过程;提示用户输入;读取用户输入;计算过程;计算机过输出过程;提示结果输出;输出计算结果END main代码框架;-main PRO
18、C;-exitmain ENDP;-GetNum PROC;-exitmain ENDP;-ArraySum PROC;-exitmain ENDP;-DispSum PROC;-exitmain ENDP汇编语言程序设计-朱明34过程化程序设计 自上而下的程序设计方法整数求和问题 完善框架中的代码内容 可能需要的调用一些功能过程 如何在屏幕上显示字符串?如何获取用户输入的数值?如何把计算结果显示在屏幕上?囧rz,其实这些过程不需要自己写的 在irvine32.inc链接库中都提供了这些功能 回顾一下第二章的内容,已经编译成为机器码的链接库是在哪一个阶段和源代码汇编生成的目标文件结合在一起的?
19、汇编语言程序设计-朱明35过程化程序设计 在屏幕上显示字符串的过程WriteString 在标准输出上显示一个以空字符结尾的字符串 要显示的字符串的偏移保存在EDX中 获取用户输入的过程ReadInt 从标准输入读取一个32位的有符号数并保存在EAX中Str1BYTE“Oh,the beautiful hawaii”,0movedx,OFFSET Str1callWriteStringintVal SDWORD?callReadIntmovintVal,eax汇编语言程序设计-朱明36过程化程序设计 在屏幕上显示计算的结果WriteInt 以十进制的形式在标准输出上输出32位有符号整数 程序中
20、其他功能的过程 输出一个我们意义上的换行,还记得是什么控制符?Crlf:向标准输出上输出0Dh和0Ah两个控制符 清除标准输出的内容,以便用户更好的观察程序输出 Clrscr:通常在程序的开始时候调用 程序中其他可能使用的指令 LOOP、POP以及PUSH相关指令moveax,14017088callWriteInt汇编语言程序设计-朱明37章节回顾 LOOP循环指令的应用方法和跳转要求 无条件跳转指令JMP的用法 操作数间接寻址和变址操作数间接寻址的形式 通过间接寻址实现对数组的访问 过程的定义要求、过程的写法与格式要求 过程的调用和过程的返回,以及对应过程中堆栈的使用情况 堆栈的压栈操作和
21、弹栈操作,以及相关的指令 过程化的程序设计方法及其相关步骤汇编语言程序设计-朱明38章节回顾 以下的问题我们应当轻松回答 IA-32结构中的哪一个寄存器与LOOP联合使用作为计数器?该寄存器中的值为多少时LOOP不再跳转?通过寄存器进行操作数间接寻址和变址操作数间接寻址时,寄存器中应分别保存什么内容?如何定义一个过程的开始以及过程的结束?如何调用一个过程?过程中什么指令表示过程的返回?哪些指令涉及到堆栈的压栈和弹栈操作?保护模式下压栈的过程中,堆栈指针ESP的值和压栈的数据是按照什么顺序变化的?汇编语言程序设计-朱明39思考问题 课后的一个作业 讲义中Page16页的问题 编写一个可以实现计算从1开始到1000以内的任意自然数连续相加的汇编语言程序,占成绩10%下次课上课之前发送至姓名_班级_学号,附件形式发送代码 自己尝试完成 在Page31所提出的问题 参考Page32Page36中所涉及的结构和过程40 结束语结束语