汇编语言学习指南(三)

“汇编语言”作为一门语言,对应于高级语言的编译器,我们需要一个“汇编器”来把汇编语言原文件汇编成机器可执行的代码。高级的汇编器如MASM, TASM等等为我们写汇编程序提供了很多类似于高级语言的特征,比如结构化、抽象等。在这样的环境中编写的汇编程序,有很大一部分是面向汇编器的伪指令,已经类同于高级语言。现在的汇编环境已经如此高级,即使全部用汇编语言来编写windows的应用程序也是可行的,但这不是汇编语言的长处。汇编语言的长处在于编写高效且需要对机器硬件精确控制的程序。而且我想这里的人学习汇编的目的多半是为了在破解时看懂反汇编代码,很少有人真的要拿汇编语言编程序吧?(汗......)

好了,言归正传。大多数汇编语言书都是面向汇编语言编程的,我的帖是面向机器和反汇编的,希望能起到相辅相成的作用。有了前面两篇的基础,汇编语言书上对大多数指令的介绍应该能够看懂、理解了。这里再讲一讲一些常见而操作比较复杂的指令。我这里讲的都是机器的硬指令,不针对任何汇编器。

无条件转移指令jmp:

这种跳转指令有三种方式:短(short),近(near)和远(far)。短是指要跳至的目标地址与当前地址前后相差不超过128字节。近是指跳转的目标地址与当前地址在用一个段内,即CS的值不变,只改变EIP的值。远指跳到另一个代码段去执行,CS/EIP都要改变。短和近在编码上有所不同,在汇编指令中一般很少显式指定,只要写 jmp 目标地址,几乎任何汇编器都会根据目标地址的距离采用适当的编码。远转移在32位系统中很少见到,原因前面已经讲过,由于有足够的线性空间,一个程序很少需要两个代码段,就连用到的系统模块也被映射到同一个地址空间。

jmp的操作数自然是目标地址,这个指令支持直接寻址和间接寻址。间接寻址又可分为寄存器间接寻址和内存间接寻址。举例如下(32位系统):

jmp 8E347D60 ;直接寻址段内跳转
jmp EBX ;寄存器间接寻址:只能段内跳转
jmp dword ptr [EBX] ;内存间接寻址,段内跳转
jmp dword ptr [00903DEC] ;同上
jmp fward ptr [00903DF0] ;内存间接寻址,段间跳转

解释:
在32位系统中,完整目标地址由16位段选择子和32位偏移量组成。因为寄存器的宽度是32位,因此寄存器间接寻址只能给出32位偏移量,所以只能是段内近转移。在内存间接寻址时,指令后面是方括号内的有效地址,在这个地址上存放跳转的目标地址。比如,在[00903DEC]处有如下数据:7C 82 59 00 A7 01 85 65 9F 01

内存字节是连续存放的,如何确定取多少作为目标地址呢?dword ptr 指明该有效地址指明的是双字,所以取
0059827C作段内跳转。反之,fward ptr 指明后面的有效地址是指向48位完全地址,所以取19F:658501A7 做远跳转。

注意:在保护模式下,如果段间转移涉及优先级的变化,则有一系列复杂的保护检查,现在可不加理会。将来等各位功力提升以后可以自己去学习。

条件转移指令jxx:只能作段内转移,且只支持直接寻址。

=========================================
调用指令CALL:

Call的寻址方式与jmp基本相同,但为了从子程序返回,该指令在跳转以前会把紧接着它的下一条指令的地址压进堆栈。如果是段内调用(目标地址是32位偏移量),则压入的也只是一个偏移量。如果是段间调用(目标地址是48位全地址),则也压入下一条指令的完全地址。同样,如果段间转移涉及优先级的变化,则有一系列复杂的保护检查。

与之对应retn/retf指令则从子程序返回。它从堆栈上取得返回地址(是call指令压进去的)并跳到该地址执行。retn取32位偏移量作段内返回,retf取48位全地址作段间返回。retn/f 还可以跟一个立即数作为操作数,该数实际上是从堆栈上传给子程序的参数的个数(以字计)返回后自动把堆栈指针esp加上指定的数*2,从而丢弃堆栈中的参数。这里具体的细节留待下一篇讲述。

虽然call和ret设计为一起工作,但它们之间没有必然的联系。就是说,如果你直接用push指令向堆栈中压入一个数,然后执行ret,他同样会把你压入的数作为返回地址,而跳到那里去执行。这种非正常的流程转移可以被用作反跟踪手段。

==========================================

中断指令INT n

在保护模式下,这个指令必定会被操作系统截获。在一般的PE程序中,这个指令已经不太见到了,而在DOS时代,中断是调用操作系统和BIOS的重要途径。现在的程序可以文质彬彬地用名字来调用windows功能,如 call user32!getwindowtexta。从程序角度看,INT指令把当前的标志寄存器先压入堆栈,然后把下一条指令的完全地址也压入堆栈,最后根据操作数n来检索“中断描述符表”,试图转移到相应的中断服务程序去执行。通常,中断服务程序都是操作系统的核心代码,必然会涉及到优先级转换和保护性检查、堆栈切换等等,细节可以看一些高级的教程。

与之相应的中断返回指令IRET做相反的操作。它从堆栈上取得返回地址,并用来设置CS:EIP,然后从堆栈中弹出标志寄存器。注意,堆栈上的标志寄存器值可能已经被中断服务程序所改变,通常是进位标志C, 用来表示功能是否正常完成。同样的,IRET也不一定非要和INT指令对应,你可以自己在堆栈上压入标志和地址,然后执行IRET来实现流程转移。实际上,多任务操作系统常用此伎俩来实现任务转换。

广义的中断是一个很大的话题,有兴趣可以去查阅系统设计的书籍。

============================================
装入全指针指令LDS,LES,LFS,LGS,LSS

这些指令有两个操作数。第一个是一个通用寄存器,第二个操作数是一个有效地址。指令从该地址取得48位全指针,将选择符装入相应的段寄存器,而将32位偏移量装入指定的通用寄存器。注意在内存中,指针的存放形式总是32位偏移量在前面,16位选择符在后面。装入指针以后,就可以用DS:[ESI]这样的形式来访问指针指向的数据了。

============================================
字符串操作指令

这里包括CMPS,SCAS,LODS,STOS,MOVS,INS和OUTS等。这些指令有一个共同的特点,就是没有显式的操作数,而由硬件规定使用DS:[ESI]指向源字符串,用ES:[EDI]指向目的字符串,用AL/AX/EAX做暂存。这是硬件规定的,所以在使用这些指令之前一定要设好相应的指针。

时间: 2024-09-24 06:46:57

汇编语言学习指南(三)的相关文章

shell脚本学习指南[三](Arnold Robbins & Nelson H.F. Beebe著)_linux shell

今天木有冷笑话,只有一个噩耗.噩耗是:今天木有冷笑话!!!不要总想着冷笑话嘛,有点追求,听毛主席的话:好好学习,天天向上! 第七章输入输出.文件与命令执行 学C的应该了解标准输入输出和错误输出吧?感觉总打很多字进度太慢,所以一直在省略类似C的东西,也方便以后看这篇文章的人能够快速学完shell脚本(或者是快速看完这本书). 读取行read命令是重要方式之一,它可以自标准输入读取行后,通过shell字段切割的功能(使用$IFS)进行切分,第一部分给第一个变量,第二部分给第二个,类推.如果切割单词多

汇编语言学习指南(二)

汇编指令的操作数可以是内存中的数据, 如何让程序从内存中正确取得所需要的数据就是对内存的寻址. INTEL 的CPU 可以工作在两种寻址模式:实模式和保护模式. 前者已经过时,就不讲了, WINDOWS 现在是32位保护模式的系统, PE 文件就基本是运行在一个32位线性地址空间, 所以这里就只介绍32位线性空间的寻址方式. 其实线性地址的概念是很直观的, 就想象一系列字节排成一长队,第一个字节编号为0, 第二个编号位1, .... 一直到4294967295(十六进制FFFFFFFF,这是32

汇编语言学习指南(一)

汇编语言和CPU以及内存,端口等硬件知识是连在一起的. 这也是为什么汇编语言没有通用性的原因. 下面简单讲讲基本知识(针对INTEL x86及其兼容机)============================x86汇编语言的指令,其操作对象是CPU上的寄存器,系统内存,或者立即数. 有些指令表面上没有操作数, 或者看上去缺少操作数, 其实该指令有内定的操作对象, 比如push指令, 一定是对SS:ESP指定的内存操作, 而cdq的操作对象一定是eax / edx. 在汇编语言中,寄存器用名字来访

汇编语言学习指南(四)

高级语言程序的汇编解析 在高级语言中,如C和PASCAL等等,我们不再直接对硬件资源进行操作,而是面向于问题的解决,这主要体现在数据抽象化和程序的结构化.例如我们用变量名来存取数据,而不再关心这个数据究竟在内存的什么地方.这样,对硬件资源的使用方式完全交给了编译器去处理.不过,一些基本的规则还是存在的,而且大多数编译器都遵循一些规范,这使得我们在阅读反汇编代码的时候日子好过一点.这里主要讲讲汇编代码中一些和高级语言对应的地方. 1. 普通变量.通常声明的变量是存放在内存中的.编译器把变量名和一个

《Cisco VoIP(CVOICE)学习指南(第三版)》一1.1 VoIP基础

1.1 VoIP基础 Cisco VoIP(CVOICE)学习指南(第三版) IP语音也就是人们通常所说的VoIP,不过它还有一种称谓叫做IP电话通讯(IP Telephony).其实这两个术语指的都是穿越IP网络发送语音信息,而它们的主要区别在于各自所使用的终端类型.比如说在VoIP网络中,传统的模拟或数字线路通常是通过某种网关连入到IP网络中的:而在IP电话通讯环境中,终端本身就可以直接利用IP进行通信.需要注意的是,包括本书在内,在很多关于这个问题的文献中,这两个术语都有可能交替使用. 由

《Cisco VoIP(CVOICE)学习指南(第三版)》一导读

前 言 Cisco VoIP(CVOICE)学习指南(第三版) 鉴于VoIP技术迅速获得了市场的采纳,很多电话和数据网络领域的技术员.工程师和设计师现已对这项技术日感熟悉.而诸如Cisco认证语音高级工程师(CCVP)等职业认证则能够证明一位员工或技术顾问在这个专业技术领域所具备的水准. CVOICE是众多CCVP考生在CCVP系列课程中学习的首门课程,而本书则对Cisco CVOICE 6.0课程中的内容进行了详细的介绍.6.0在CVOICE 5.0课程的基础上进行了重要的更新,新版课程中融入

《Cisco VoIP(CVOICE)学习指南(第三版)》一第1章 介绍VoIP网络

第1章 介绍VoIP网络 Cisco VoIP(CVOICE)学习指南(第三版) 通过学习本章内容,应当: 能够描述IP语音(VoIP).VoIP网络的组件.使用的协议以及将VoIP集成到现有数据网络中所需要考虑的服务: 能够描述各种类型的语音网关,以及如何在不同IP电话环境中使用这些网关. 第1章 介绍VoIP网络 IP语音(Voice over IP)使启用了语音功能的路由器1能够在IP网络上承载语音流量,如电话呼叫和传真.本章将介绍VoIP基础.各种类型的VoIP网关以及如何在不同的IP电

《Cisco VoIP(CVOICE)学习指南(第三版)》一1.3 小结

1.3 小结 Cisco VoIP(CVOICE)学习指南(第三版) 本章主要涵盖了以下主要内容. Cisco统一通信系统技术架构令数据.语音和视频能够在单一的标准IP网络架构中传递,将各类通信集成在一起. VoIP技术家族使用IP网络传递语音应用,如电话.语音及时通信和电话会议. VoIP使用H.323.MGCP.SIP和SCCP呼叫信令和呼叫控制协议. 信令协议模型包括2个协议类别:端到端(peer-to-peer)和服务器/客户端(client/ server). 在数据网络中配置语音应用

《Cisco VoIP(CVOICE)学习指南(第三版)》一1.4 习题

1.4 习题 Cisco VoIP(CVOICE)学习指南(第三版)习题的答案请参考书后附录. (1)请指出提供CAC.带宽控制和管理.地址转换的VoIP网络组件. a.网关 b.网守 c.MCU d.呼叫代理 (2)下列信令协议中,哪2个是端到端(peer-to-peer)协议? a.H.323 b.MGCP c.SIP d.SCCP (3)cRTP压缩哪3种数据包的头部? a.数据链路 b.IP c.TCP d.UDP e.RTP (4)下列哪项是对RTCP功能的最佳描述? a.RTCP为语