第 5 章 32 位汇编程序设计

52
第 5 第 32 第第第第第第第 80186 以以 CPU 以 8086 以以以以以以以以以以以 DOS 以以 Windows 以以以以以 32 以以以以以以以以以以 DOS 以以 Debug 以 以以以W32Dasm 以以 Windows 以以

Upload: sereno

Post on 19-Jan-2016

112 views

Category:

Documents


0 download

DESCRIPTION

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

TRANSCRIPT

Page 1: 第 5 章  32 位汇编程序设计

第 5 章 32 位汇编程序设计

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

Page 2: 第 5 章  32 位汇编程序设计

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 微处理器的功能。

Page 3: 第 5 章  32 位汇编程序设计

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 字节

Page 4: 第 5 章  32 位汇编程序设计

(2) 在使用寄存器间接寻址、寄存器相对寻址或相对的基址变址寻址时,既可以用 16 位的寄存器,又可以使用 32 位的寄存器。

例如: MOV AX , [BX] MOV DX , [EBX]

MOV EAX , [EBX+80H] MOV EAX , [EBX+ESI+0400H]

Page 5: 第 5 章  32 位汇编程序设计

(3) 80386 的所有 32 位通用寄存器都可以作为偏移地址参加寻址,而在 8086/8088/80186/80286 中的 AX 、 DX 、 CX 寄存器不能用来存放存储器操作数的偏移地址。

例如: MOV AX , [ECX] ;正确 MOV BX , [EAX] ;正确 MOV BX , [AX] ;在 16 位下错误

Page 6: 第 5 章  32 位汇编程序设计

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

Page 7: 第 5 章  32 位汇编程序设计

(5) 32 位变址寄存器的值可以乘上一个比例常数 ( 如 1 , 2 , 4 , 8) ,乘上比例常数的变址方式对于访问数组等数据结构特别有效。例如:

MOV EAX , [ESI*2]MOV EAX , [EBX+ESI*8]MOV EAX , [EBX+ESI*4+0400H]

Page 8: 第 5 章  32 位汇编程序设计

由此可见, 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 位的值。

Page 9: 第 5 章  32 位汇编程序设计

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

Page 10: 第 5 章  32 位汇编程序设计

c. 32 位通用寄存器进栈指令 PUSHAD 和出栈指令 POPAD. 这两条指令是 32 位 CPU 新扩展的指令:

PUSHAD ; 顺序将 EAX/ECX/EDX/EBX/ESPEBP/ESI/EDI

的内容压入堆栈, SP←SP-32POPAD

; 功能和 PUSHAD 指令功能相反, SP←SP+32

Page 11: 第 5 章  32 位汇编程序设计

(2) 标志传送 标志传送指令增加了两条: PUSHFD ;将 EFLAGS 的内容压入堆栈,

堆栈中 D16D17 两位被清 0POPFD ;将堆栈内容弹出到 EFLAGS ,堆栈中 D20D19 两位被清 0 , D16 保持不变

Page 12: 第 5 章  32 位汇编程序设计

(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 位远指针

Page 13: 第 5 章  32 位汇编程序设计

2. 算术运算指令的扩展 (1) 乘除法指令IMUL r16 , r16/m16/i8/i16 ; r16← r16*r16/m16/i8/i16IMUL r16 , r16/m16 , i8/i16 ; r16← r16/m16*i8/i16IMUL r32 , r32/m32/i8/i32 ; r32← r32*r32/m32/i8/i16IMUL r32 , r32/m32 , i8/i32 ; r16← r32/m32*i8/i16

指令说明:新增的这些指令要求目的操作数和源操作数的长度要相同。对于 8 位立即数 i8 要进行符号扩展,扩展后为 16/32 位。

Page 14: 第 5 章  32 位汇编程序设计

(2) 符号扩展指令80386 新扩展的指令有:

CWDE ;将 AX符号扩展为 EAXCDQ ;将 EAX符号扩展为 EDX.EAXMOVSX 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零位扩展

Page 15: 第 5 章  32 位汇编程序设计

3. 位操作指令扩展移位指令从 80186 开始支持一个立即数做

移位次数,其指令格式为:SHL/SHR/SAL/SAR/ROL/ROR/RCL/RCR r

eg/mem , 1/cl/i8

Page 16: 第 5 章  32 位汇编程序设计

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

Page 17: 第 5 章  32 位汇编程序设计

(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段寄

存器不能被段超越。

Page 18: 第 5 章  32 位汇编程序设计

(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段寄存器可以被段超越。

Page 19: 第 5 章  32 位汇编程序设计

80386 新增指令 80386CPU 中通用寄存器由 32 位寄存器组成,

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

Page 20: 第 5 章  32 位汇编程序设计

80486 新增指令 80486CPU 不仅包括 80386CPU 的结构,还包括了 80

387协处理器 FPU 的结构,且在此基础上增加了 8KB的 Cache高速缓冲存储器,它的最高内部时钟频率达到了 100MHZ。采用了精简指令系统集计算机技术RISC 和指令流水线方式,使指令的执行速度及其他性能有了更大的提高,且可以直接执行 8087 的所有浮点运算指令。

80486 的指令系统在 80386 指令系统的基础上增加了6 条指令,其中, INVLPG 、 INVD及WBINVD 三条专用于 Cache管理,一般用户不需使用,另外三条 XADD 、 CMPXCHG 和 BSWAP 指令是可供系统应用程序使用的指令。

Page 21: 第 5 章  32 位汇编程序设计

Pentium 新增指令 Pentium CPU仍为 32 位结构,地址总线为 32

位,但外部数据线为 64 位,内部时钟频率为 60MHZ~ 200MHZ。 Pentium CPU 对浮点处理单元进行了重大改进,增加了专用的加法、乘法和除法单元;采用具有两条流水线的超标量技术;对常用的简单指令用硬件实现等,进一步提高了 Pentium CPU 的整体性能。

Pentium CPU 指令系统中新增加了一条 8 字节比较交换指令 CMPXCHG8B ,一条处理器识别指令 CPUID , 4 条系统专用指令 RDTSC 、RDMSR、 WRMSR、 RSM 。

Page 22: 第 5 章  32 位汇编程序设计

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 。

Page 23: 第 5 章  32 位汇编程序设计

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

Page 24: 第 5 章  32 位汇编程序设计

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

差别

Page 25: 第 5 章  32 位汇编程序设计

DOS 32 位程序举例 例 1 :将一个 64 位数据算术左移 4 位分析:本例采用 EDX.EAX 保存 64 位数据,用 4次循环实现移位。

.MODEL SMALL

.386 ;采用 32 位指令, 16 位段模式

.STACK

.DATAQVAR DQ 1234567887654321H

.CODE .STARTUP

MOV EAX , DWORD PTR QVARMOV EDX DWORD PTR QVAR [4]MOV ECX , 4

NEXT:SHL EAX , 1RCL EDX , 1LOOP NEXTMOV DWORD PTR QVAR, EAXMOV DWORD PTR QVAR[4] , EDX

.EXIT 0END

Page 26: 第 5 章  32 位汇编程序设计

Windows 下 32 位汇编程序 若较好地掌握了 Windows 下的汇编程序开发,

可以让我们深刻地理解高级语言是怎么来的,而且在学习反病毒技术、软件的加密解密方面这是必须的。在高级语言的开发中涉及到程序的调试,也要用到汇编语言。

Windows 下汇编语言的开发使用软件Masm32 或 Tasm32 ,本书使用的是 Masm32 。程序的调试使用 W32dasm 、 Soft-Ice 等软件。

Page 27: 第 5 章  32 位汇编程序设计

Windows 汇编语言特点 DOS 下的汇编程序是“指令 + 中断”,而 Wind

ows 下 32 位汇编程序是“指令 +API+消息”。 API 函数 :API 是“ Application Programming I

nterface”的英文缩写,很象 DOS 下的中断。中断是系统提供的功能,在操作系统运行后就被装载在内存中,而 API函数是通过将函数所在的动态连接库装载到内存后调用函数的。

Page 28: 第 5 章  32 位汇编程序设计

在 Windows 下设计应用程序不使用 API是不可能的,有些高级语言看似没有使用 API ,只不过它们提供的模块对 API进了封装。

API 是 Windows 的基础, API 包含在众多扩展名为 dll 的动态连接库中,三个关键的动态连接库文件是:

Page 29: 第 5 章  32 位汇编程序设计

Kernel32.dll :系统服务功能。包含内存管理、任务管理和文件操作等 API函数。一般情况下都要使用该动态连接库。也许一个程序什么功能也没有,但不能没有类似 DOS 下退出内存的 .EXIT 0 指令,在 Windows 下为API函数 ExitProcess 。

Gui32.dll :图形设备接口。提供显示文本和图形等 API函数。 Windows 程序最大的一个特点是窗口,如果设计的程序要包含窗口,则需要该库中的函数,包括窗口的建立、显示、事件处理和销毁。

User32.dll :用户接口服务。提供建立窗口和传送消息的 API函数。用户点击按钮或拖动窗口,界面之所以出现相应的变化,因为系统对不同的用户操作用消息来描述,不同的消息又对应不同的函数,由它们去处理。

Page 30: 第 5 章  32 位汇编程序设计

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

Page 31: 第 5 章  32 位汇编程序设计

消息本身是作为一个用 MSG命名的结构传递给应用程序的,这个结构中包含了消息的类型等信息。其定义如下:

MSG structHwnd dword ? ;消息目的窗口句柄Message dword ?

;消息常量标识符,是用 WM_开头的预定义常量wParam dword ? ; 32 位消息带的参数 1lParam dword ? ; 32 位消息带的参数 2Time dword ? ;消息创建时的时间Pt POINT <> ;消息创建时的鼠标位置

MSG ends

Page 32: 第 5 章  32 位汇编程序设计

MASM32 开发环境

Steve Hutchesson 的免费软件包 编辑器 geditor.exe MASM 6.14汇编程序和链接程序 相当完整的 Win32 的包含文件、库文件

以及教程和示例等

Page 33: 第 5 章  32 位汇编程序设计

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

Page 34: 第 5 章  32 位汇编程序设计

MASM32界面

Page 35: 第 5 章  32 位汇编程序设计

.386 ;伪指令,还可以是 .486 .586

.MODEL Flat, STDCALL ; 内存模式伪指令

.DATA ; STDCALL告诉编译器参数的传递约定。 ; 初始化数据定义于此  ...... .DATA? ; 未初始化数据定义于此.......CONST ; 常量定义于此.......CODE; 标号 ;start :; 代码部分..... end <label> ;end start

Win32ASM 程序结构

Page 36: 第 5 章  32 位汇编程序设计

一个最简单的 Win32 汇编语言程序

显示标准 Windows 消息窗口的程序消息框显示:汇编语言并不难

标题:欢迎进入 32 位 Windows 世界

将下面的代码存为 aa.asm ,然后选择菜单“ Project”“Assemble & Link” ,如果没有错误的话,会生成 aa.exe 。双击aa.exe 就可以执行它。

Win32ASM 程序示例

Page 37: 第 5 章  32 位汇编程序设计

.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

API区别大小写

包含对系统常量和 API函数等的声明

包含 API函数的库文件

Page 38: 第 5 章  32 位汇编程序设计

.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

显示消息框API调用返回操作系统API调用

Page 39: 第 5 章  32 位汇编程序设计

W32Dasm反汇编工具简介 W32Dasm 是著名的静态反汇编工具,

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

Page 40: 第 5 章  32 位汇编程序设计

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

Page 41: 第 5 章  32 位汇编程序设计

W32Dasm ver 8.3

Page 42: 第 5 章  32 位汇编程序设计

W32Dasm 的反汇编代码阅读 我们以上个例子生成的可执行文件进行反汇编,然后分析其反汇编文件结构。下面按行进行说明:

反汇编的文件名为 test.exe 。 代码段在文件中偏移地址为 400h ,大小为 200h 。 数据段在文件中偏移地址为 800h ,大小为 200h 。 节个数为 3 ,程序内存中装载的虚拟地址为 0040000

0h 。节是可执行文件中代码、数据和资源的基本单位。

节:性质相同的数据放在一个连续区域内,该区域叫节

Page 43: 第 5 章  32 位汇编程序设计

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

节名 .rdata ,内存中相对于 ImageBase的偏移值为 2000h ,文件中偏移为 600h ,大小为 200h ,节属性值为 40000040h 。

Page 44: 第 5 章  32 位汇编程序设计

节名 .data ,内存中相对于 ImageBase的偏移值为 3000h ,文件中偏移为 800h ,大小为 200h ,节属性值为 0c0000040h 。定义的全局变量一般在该节。

节名 .rsrc ,内存中相对于 ImageBase的偏移值为 4000h ,文件中偏移为 0a00h ,大小为 600h ,节属性值为 0c0000040h 。文件中使用到的资源一般在该节。

Page 45: 第 5 章  32 位汇编程序设计

程序有一个菜单资源,但格式不清楚。 程序无对话框资源。 导入函数信息。  有两个导入模块。 导入模块 1 为 kernel32.dll ,模块 2 为 user32.

dll 。 调用模块 1 中函数 ExitProcess ,在内存中地

址为 0040205ch ,函数序号为 0075h 。 调用模块 2 中函数 MessageBoxA ,在内存中

地址为 00402078h ,函数序号为 01bbh 。

Page 46: 第 5 章  32 位汇编程序设计

导出函数个数为 0 。一般只有 dll文件才有导出模块。

汇编代码列表。 代码部分在节 .text 。 程序入口在内存 00401000h ,在文件偏

移位置 1600h 。

Page 47: 第 5 章  32 位汇编程序设计

后面部分为汇编代码部分。在原程序中调用MessageBox 的方法为: invoke MessageBox , 0 , offset text1 , offset text

2 , MB_OK

在反汇编中,我们可以看出实际的代码为:push 00000000h ;实际为常量 MB_OKpush 0040300Fh ;字符串的偏移地址push 00403000h ;字符串的偏移地址push 00000000h ;窗口句柄call 00401020h ;跳转到 MessageBox

Page 48: 第 5 章  32 位汇编程序设计

Windows 程序的调试 本节通过举例怎样反汇编一个程序并进行调试和修改。

可以使用 Soft-Ice 调试 Windows 程序,我们这里使用 W32dasm实现对 test.exe 的修改,对照图 5-8 ,修改后的结果如图 5-19 。其原理是将调用 MessageBox 传递的参数进行修改,修改后如下:

push 00000000h ;不变push 00403000h ;修改push 00403000h ;修改 push 00000000h ;不变 call 00401020h ;不变

Page 49: 第 5 章  32 位汇编程序设计

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

Page 50: 第 5 章  32 位汇编程序设计

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

Page 51: 第 5 章  32 位汇编程序设计

(3) 点击按钮“ Patch Code”,出现界面如图 5-23 ,在第二行的编辑框中输入修改后的指令为“push 00403000”,按回车键,该行指令会转移到下面的编辑框。

(4) 点击“ Applay patch”,然后点击“ Close”关闭该对话框。在弹出的界面中选择“是”,看到程序代码已经修改。

Page 52: 第 5 章  32 位汇编程序设计

(5) 选择菜单“ EditQuikEdit”,弹出相应界面。前面的修改可以用来验证是否修改正确,真正的修改在该界面。

(6) 点击“ Save 保存”,在弹出的界面上选择确定,修改后文件选择另保存 ptest.exe 。运行ptest.exe ,程序界面已经变化。