1 / 52

第 5 章 32 位汇编程序设计

第 5 章 32 位汇编程序设计. 80186 以后 CPU 在 8086 基础上增加的常用指令。 在 DOS 下和 Windows 下如何使用 32 位指令设计程序。 区别于 DOS 下的 Debug ,如何用 W32Dasm 调试 Windows 程序。. 5.1 32 位指令系统.

sereno
Download Presentation

第 5 章 32 位汇编程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第5章 32位汇编程序设计 80186以后CPU在8086基础上增加的常用指令。 在DOS下和Windows下如何使用32位指令设计程序。 区别于DOS下的Debug,如何用W32Dasm调试Windows程序。

  2. 5.1 32位指令系统 • Intel公司于1985年正式公布了32位微处理器80386。80386采用32位指令系统的结构,被Intel公司称为英特尔结构,简称IA(1ntel Architecture)结构,并明确宣布作为后续80x86微处理器的标准。在此基础上,Intel公司又相继推出了80486、Pentium、MMX Pentium 、Pentium Pro、Pentium II、Pentium III、Pentium Ⅳ等微处理器,它们都继承了80386的32位指令系统,同时又新增了若干条专用指令;另外还在32位整数指令系统的基础上加入了浮点指令、整数多媒体MMX指令和浮点多媒体SSE指令,极大地丰富了Intel 80x86微处理器的指令系统,有效地增强了Intel 80x86微处理器的功能。

  3. 32位的寻址方式 • Intel 80x86系列的微处理器32位CPU相对于16位CPU寻址方式的主要区别有: (1) 32位寻址方式的操作数可以是8位、16位或32位,包括32位的立即数。 例如: MOV EAX,12345678H ;源操作数为32位立即数 MOV EAX,EBX ;两个寄存器均为32位 MOV EAX,[2000H] ;因为EAX为32位,从DS:[2000H]处取4字节

  4. (2) 在使用寄存器间接寻址、寄存器相对寻址或相对的基址变址寻址时,既可以用16位的寄存器,又可以使用32位的寄存器。 例如: MOV AX,[BX] MOV DX,[EBX] MOV EAX,[EBX+80H] MOV EAX,[EBX+ESI+0400H]

  5. (3) 80386的所有32位通用寄存器都可以作为偏移地址参加寻址,而在8086/8088/80186/80286中的AX、DX、CX寄存器不能用来存放存储器操作数的偏移地址。 例如: MOV AX,[ECX] ;正确 MOV BX,[EAX] ;正确 MOV BX,[AX] ;在16位下错误

  6. (4) 80386的所有32位通用寄存器都可以作为基地址寄存器使用,除了ESP寄存器以外都可以作为变址寄存器使用。

  7. (5) 32位变址寄存器的值可以乘上一个比例常数(如1,2,4,8),乘上比例常数的变址方式对于访问数组等数据结构特别有效。 例如: MOV EAX,[ESI*2] MOV EAX,[EBX+ESI*8] MOV EAX,[EBX+ESI*4+0400H]

  8. 由此可见,16位存储器操作数的寻址方式的组成公式为: 16位有效地址=基址寄存器(BX/BP)+变址寄存器(SI/DI)+8/16位的偏移量 其中基址寄存器只能是BX或BP,变址寄存器只能是SI或DI。 而32位存储器操作数的寻址方式的组成公式为: 32位有效地址=基址寄存器+(变址寄存器*比例)+8/32位的偏移量 其中基址寄存器为任何8个32位通用寄存器之一,变址寄存器为除ESP之外的任何32位通用寄存器之一,比例可以是1、2、4或8,代表操作数的长度是1、2、4或8字节,位移量可以是8或32位的值。

  9. 32位扩展指令 • 1.数据传送指令的扩展 (1) 堆栈操作 a. 进栈指令PUSH和出栈指令POP b.16位通用寄存器进栈指令PUSHA和出栈指令POPA 从80186开始引入了如下指令: PUSHA ;顺序将AX/CX/DX/BX/SP/BP/SI/DI的内容 压入堆栈,SP←SP-16 POPA ;功能和PUSHA指令功能相反,SP←SP+16

  10. c. 32位通用寄存器进栈指令PUSHAD和出栈指令POPAD. 这两条指令是32位CPU新扩展的指令: PUSHAD ;顺序将 EAX/ECX/EDX/EBX/ESPEBP/ESI/EDI的内容压入堆栈,SP←SP-32 POPAD ;功能和PUSHAD指令功能相反,SP←SP+32

  11. (2) 标志传送 标志传送指令增加了两条: PUSHFD ;将EFLAGS的内容压入堆栈,堆栈中D16D17两位被清0 POPFD ;将堆栈内容弹出到EFLAGS,堆栈中D20D19两位被清0,D16保持不变

  12. (3) 地址传送 地址传送指令增加了三条: LFS r16/r32, mem ;FS:r16/r32←存储单元的32/48位远指针 LGS r16/r32, mem ;GS:r16/r32←存储单元的32/48位远指针 LSS r16/r32, mem ;SS:r16/r32←存储单元的32/48位远指针

  13. 2. 算术运算指令的扩展 (1) 乘除法指令 IMUL r16,r16/m16/i8/i16 ;r16← r16*r16/m16/i8/i16 IMUL r16,r16/m16,i8/i16 ;r16← r16/m16*i8/i16 IMUL r32,r32/m32/i8/i32 ;r32← r32*r32/m32/i8/i16 IMUL r32,r32/m32,i8/i32 ;r16← r32/m32*i8/i16 指令说明:新增的这些指令要求目的操作数和源操作数的长度要相同。对于8位立即数i8要进行符号扩展,扩展后为16/32位。

  14. (2) 符号扩展指令 80386 新扩展的指令有: CWDE ;将AX符号扩展为EAX CDQ ;将EAX符号扩展为EDX.EAX MOVSX r16,r8/m8 ;r16←将r8/m8符号扩展 MOVZX r16,r8/m8 ;r16←将r8/m8零位扩展 MOVSX r32,r8/m8/r16/m16 ;r32←将r8/m8/r16/m16符号扩展 MOVZX r32,r8/m8/r16/m16 ;r32←将r8/m8/r16/m16零位扩展

  15. 3. 位操作指令扩展 移位指令从80186开始支持一个立即数做移位次数,其指令格式为: SHL/SHR/SAL/SAR/ROL/ROR/RCL/RCR reg/mem,1/cl/i8

  16. 4. 串操作指令扩展 从80186开始支持端口的串操作,配合重复前缀指令就能够实现用一条指令连续进行输入或输出操作,大大提高了CPU的I/O操作能力。

  17. (1) 串输入 指令格式及功能: INSB/INSW/INSD ;ES:[DI/EDI] ←DX指定的输入端口,DI/EDI←DI/EDI±1/2/4 指令说明:INS指令从由DX指定的输入端口中输入一 个字节(INSB)或一个字(INSW)或一个双字INSD) 数据到由ES:[DI/EDI]指定的存储单元中,且能使 DI/EDI自动±1或±2或±4;DX内容保持不变。ES段寄 存器不能被段超越。

  18. (2) 串输出 指令格式及功能: OUTSB/OUTSW/OUTSD ;DX指定的输出端口←DS:[SI/ESI],SI/ESI←SI/ESI±1/2/4 指令说明:该指令实现从由DS:[SI/ESI]指定的内存单元中的一个字节(OUTSB)或一个字(OUTSW)或一个双字(OUTSD)数据到由DX指定输出端口中,且能使SI/ESI自动±1或±2或±4;DX内容保持不变。DS段寄存器可以被段超越。

  19. 80386新增指令 • 80386CPU中通用寄存器由32位寄存器组成,因此所有16位指令都有其相应的32位指令形式,以支持32位数据类型的操作。操作数可为8位、16位或32位,并且可以使用32位寻址方式。80386的执行单元中新增了一个“桶型”移位器,所以可以实现快速移位操作,新增的指令主要是有关位操作的。另外,80386还增加了条件设置指令,以及对控制、调试和测试寄存器的传送指令。

  20. 80486新增指令 • 80486CPU不仅包括80386CPU的结构,还包括了80387协处理器FPU的结构,且在此基础上增加了8KB的Cache高速缓冲存储器,它的最高内部时钟频率达到了100MHZ。采用了精简指令系统集计算机技术RISC和指令流水线方式,使指令的执行速度及其他性能有了更大的提高,且可以直接执行8087的所有浮点运算指令。 • 80486的指令系统在80386指令系统的基础上增加了6条指令,其中,INVLPG、INVD及WBINVD三条专用于Cache管理,一般用户不需使用,另外三条XADD、CMPXCHG和BSWAP指令是可供系统应用程序使用的指令。

  21. Pentium新增指令 • Pentium CPU仍为32位结构,地址总线为32位,但外部数据线为64位,内部时钟频率为60MHZ~200MHZ。Pentium CPU对浮点处理单元进行了重大改进,增加了专用的加法、乘法和除法单元;采用具有两条流水线的超标量技术;对常用的简单指令用硬件实现等,进一步提高了Pentium CPU的整体性能。 • Pentium CPU指令系统中新增加了一条8字节比较交换指令CMPXCHG8B,一条处理器识别指令CPUID,4条系统专用指令RDTSC、RDMSR、WRMSR、RSM。

  22. Pentium pro新增指令 • Pentium Pro CPU的地址总线为36位,可以寻址的主存空间可达64GB。Pentium Pro CPU内含一级Cache 为16 KB,二级Cache 为256/512KB;扩展了超标量技术,具有三个整数处理单元和一个浮点处理单元,能同时执行三条指令,并对32位指令进行了优化处理。 • Pentium Pro CPU在Pentium指令系统的基础上新增了3条实用的指令CMOV、RDPMC、UD2。

  23. DOS下32位汇编程序 • 32位程序编写规范 32位指令的程序设计方法和我们在前面讲过的16位指令的程序设计方法基本相同。但在编写完整的汇编程序时,需注意以下问题:

  24. 指定汇编程序识别新指令 • 处理16位段和32位段 • 注意有些指令在16位段和32位段的差别

  25. DOS 32位程序举例 例1:将一个64位数据算术左移4位 分析:本例采用EDX.EAX保存64位数据,用4次循环实现移位。 .MODEL SMALL .386 ;采用32位指令,16位段模式 .STACK .DATA QVAR DQ 1234567887654321H .CODE .STARTUP MOV EAX,DWORD PTR QVAR MOV EDX DWORD PTR QVAR [4] MOV ECX,4 NEXT: SHL EAX,1 RCL EDX,1 LOOP NEXT MOV DWORD PTR QVAR,EAX MOV DWORD PTR QVAR[4],EDX .EXIT 0 END

  26. Windows下32位汇编程序 • 若较好地掌握了Windows下的汇编程序开发,可以让我们深刻地理解高级语言是怎么来的,而且在学习反病毒技术、软件的加密解密方面这是必须的。在高级语言的开发中涉及到程序的调试,也要用到汇编语言。 • Windows下汇编语言的开发使用软件Masm32或Tasm32,本书使用的是Masm32。程序的调试使用W32dasm、Soft-Ice等软件。

  27. Windows汇编语言特点 • DOS下的汇编程序是“指令+中断”,而Windows下32位汇编程序是“指令+API+消息”。 • API函数:API是“Application Programming Interface”的英文缩写,很象DOS下的中断。中断是系统提供的功能,在操作系统运行后就被装载在内存中,而API函数是通过将函数所在的动态连接库装载到内存后调用函数的。

  28. 在Windows下设计应用程序不使用API是不可能的,有些高级语言看似没有使用API,只不过它们提供的模块对API进了封装。在Windows下设计应用程序不使用API是不可能的,有些高级语言看似没有使用API,只不过它们提供的模块对API进了封装。 • API是Windows的基础,API包含在众多扩展名为dll的动态连接库中,三个关键的动态连接库文件是:

  29. Kernel32.dll:系统服务功能。包含内存管理、任务管理和文件操作等API函数。一般情况下都要使用该动态连接库。也许一个程序什么功能也没有,但不能没有类似DOS下退出内存的.EXIT 0指令,在Windows下为API函数ExitProcess。 • Gui32.dll:图形设备接口。提供显示文本和图形等API函数。Windows程序最大的一个特点是窗口,如果设计的程序要包含窗口,则需要该库中的函数,包括窗口的建立、显示、事件处理和销毁。 • User32.dll:用户接口服务。提供建立窗口和传送消息的API函数。用户点击按钮或拖动窗口,界面之所以出现相应的变化,因为系统对不同的用户操作用消息来描述,不同的消息又对应不同的函数,由它们去处理。

  30. 消息:消息是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。

  31. 消息本身是作为一个用MSG命名的结构传递给应用程序的,这个结构中包含了消息的类型等信息。其定义如下:消息本身是作为一个用MSG命名的结构传递给应用程序的,这个结构中包含了消息的类型等信息。其定义如下: MSG struct Hwnd dword ? ;消息目的窗口句柄 Message dword ? ;消息常量标识符,是用WM_开头的预定义常量 wParam dword ? ;32位消息带的参数1 lParam dword ? ;32位消息带的参数2 Time dword ? ;消息创建时的时间 Pt POINT <> ;消息创建时的鼠标位置 MSG ends

  32. MASM32开发环境 Steve Hutchesson的免费软件包 • 编辑器geditor.exe • MASM 6.14汇编程序和链接程序 • 相当完整的Win32的包含文件、库文件以及教程和示例等

  33. MASM32的网络资源 • Hutch的32位MASM第8版(masm32v82r.zip) http://www.movsd.com/ • Iczelion的Win32教程 http://spiff.tripnet.se/~iczelion http://asm.yeah.net/ • API文档 http://www.microsoft.com/msdn

  34. MASM32界面

  35. Win32ASM程序结构 .386 ;伪指令,还可以是.486 .586 .MODEL Flat, STDCALL ;内存模式伪指令 .DATA ; STDCALL告诉编译器参数的传递约定。 ;初始化数据定义于此 ...... .DATA? ;未初始化数据定义于此 ...... .CONST ;常量定义于此 ...... .CODE ;标号 ;start: ;代码部分 ..... end <label> ;end start

  36. Win32ASM程序示例 • 一个最简单的Win32汇编语言程序 • 显示标准Windows消息窗口的程序 • 消息框显示:汇编语言并不难 • 标题:欢迎进入32位Windows世界 • 将下面的代码存为aa.asm,然后选择菜单“Project”“Assemble & Link”,如果没有错误的话,会生成aa.exe。双击aa.exe就可以执行它。

  37. API区别大小写 包含API函数的库文件 包含对系统常量和API函数等的声明 .386 .model flat,stdcall option casemap:none include \masm32\include\windows.inc include \masm32\include\kernel32.inc include \masm32\include\user32.inc includelib \masm32\lib\kernel32.lib includelib \masm32\lib\user32.lib

  38. 返回操作系统API调用 显示消息框API调用 .data szCaption db “欢迎进入32位Windows世界”,0 szText db “汇编语言并不难!”,0 .code start: invoke MessageBox,NULL,\ offset szText, addr szCaption,MB_OK invoke ExitProcess,NULL end start

  39. W32Dasm反汇编工具简介 • W32Dasm是著名的静态反汇编工具,它能把PE等格式的文件反汇编为易于阅读的文本文件。所谓的静态反汇编是有别于动态反汇编工具,一次完成反汇编,不能一条指令一条指令的跟踪执行的一种反汇编方式。W32Dasm只有简单的调试功能。

  40. W32Dasm的主要功能 • 保存反汇编文本文件和创建方案文件 • 跳转到代码的某个位置 • 查看导入、导出函数 • 以二进制方式查看数据段和代码段数据 • 资源定位 • 简单的动态调试功能

  41. W32Dasm ver 8.3

  42. W32Dasm 的反汇编代码阅读 • 我们以上个例子生成的可执行文件进行反汇编,然后分析其反汇编文件结构。下面按行进行说明: • 反汇编的文件名为test.exe。 • 代码段在文件中偏移地址为400h,大小为200h。 • 数据段在文件中偏移地址为800h,大小为200h。 • 节个数为3,程序内存中装载的虚拟地址为00400000h。节是可执行文件中代码、数据和资源的基本单位。 节:性质相同的数据放在一个连续区域内,该区域叫节

  43. 节名.text,内存中相对于ImageBase的偏移值为1000h,文件中偏移为400h,大小为200h,节属性值为60000020h。属性表明该节是可执行、可读和可写等特征的。该节一般包含可执行的代码。节名.text,内存中相对于ImageBase的偏移值为1000h,文件中偏移为400h,大小为200h,节属性值为60000020h。属性表明该节是可执行、可读和可写等特征的。该节一般包含可执行的代码。 • 节名.rdata,内存中相对于ImageBase的偏移值为2000h,文件中偏移为600h,大小为200h,节属性值为40000040h。

  44. 节名.data,内存中相对于ImageBase的偏移值为3000h,文件中偏移为800h,大小为200h,节属性值为0c0000040h。定义的全局变量一般在该节。节名.data,内存中相对于ImageBase的偏移值为3000h,文件中偏移为800h,大小为200h,节属性值为0c0000040h。定义的全局变量一般在该节。 • 节名.rsrc,内存中相对于ImageBase的偏移值为4000h,文件中偏移为0a00h,大小为600h,节属性值为0c0000040h。文件中使用到的资源一般在该节。

  45. 程序有一个菜单资源,但格式不清楚。 • 程序无对话框资源。 • 导入函数信息。 •  有两个导入模块。 • 导入模块1为kernel32.dll,模块2为user32.dll。 • 调用模块1中函数ExitProcess,在内存中地址为0040205ch,函数序号为0075h。 • 调用模块2中函数MessageBoxA,在内存中地址为00402078h,函数序号为01bbh。

  46. 导出函数个数为0。一般只有dll文件才有导出模块。导出函数个数为0。一般只有dll文件才有导出模块。 • 汇编代码列表。 • 代码部分在节.text。 • 程序入口在内存00401000h,在文件偏移位置1600h。

  47. 后面部分为汇编代码部分。在原程序中调用 MessageBox的方法为: invoke MessageBox,0,offset text1,offset text2,MB_OK 在反汇编中,我们可以看出实际的代码为: push 00000000h ;实际为常量MB_OK push 0040300Fh ;字符串的偏移地址 push 00403000h ;字符串的偏移地址 push 00000000h ;窗口句柄 call 00401020h ;跳转到MessageBox

  48. Windows程序的调试 • 本节通过举例怎样反汇编一个程序并进行调试和修改。可以使用Soft-Ice调试Windows程序,我们这里使用W32dasm实现对test.exe的修改,对照图5-8,修改后的结果如图5-19。其原理是将调用MessageBox传递的参数进行修改,修改后如下: push 00000000h ;不变 push 00403000h ;修改 push 00403000h ;修改 push 00000000h ;不变 call 00401020h ;不变

  49. 修改的步骤 (1) 从菜单“Open File to Disassemble”选择文件test.exe,反汇编结束后从菜单“Debug”选择“Load Process”,点击“Load”,生成受W32dasm控制的进程test.exe。

  50. (2) 选择对话框,此时焦点定位在程序的第一条指令,偏移地址为00401000h。我们要修改00401002h处的指令,但直接点击该行不管用。点击“Goto Address”,在弹出的界面中点击“OK”,焦点会跳到第二条指令,

More Related