汇编语言的准备知识,第1张

汇编语言的准备知识,第2张

作为一种语言,“汇编语言”对应的是高级语言的编译器。我们需要一个“汇编程序”将原始的汇编语言文件汇编成机器可执行代码。MASM、TASM等高级汇编语言为我们提供了许多类似于高级语言的特性,比如结构和抽象。在这种环境下编写的汇编程序,很大一部分是汇编程序的伪指令,类似于高级语言。现在汇编环境这么先进,用汇编语言写所有的windows应用都是可行的,但这不是汇编语言的优势。汇编语言的优点是编写高效的程序,这些程序需要对机器硬件进行精确控制。而且我觉得这里大部分人学汇编都是为了破解时理解反汇编代码。很少有人真的想用汇编语言编程吧?(汗.....)
好了,言归正传。汇编语言书籍大多面向汇编语言编程,我的帖子面向机器和反汇编,希望能起到补充作用。有了前两篇文章的基础,汇编语言书中大部分指令的介绍应该是可以阅读理解的。在这里,我们来谈谈一些常见而复杂的指令。我这里说的是机器的硬指令,不是针对任何汇编程序的。

无条件转移指令:

这个跳转指令有三种方式:短、近、远。Short表示要跳转到的目标地址与当前地址之差不超过128个字节。Near表示跳转的目的地址与当前地址在一个段内,即CS的值不变,只改变EIP的值。意味着跳转到另一个代码段执行,CS/EIP会被改变。短和近在编码上是不一样的。通常,它们很少在汇编指令中明确指定。只要写出jmp目标地址,几乎任何汇编器都会根据目标地址的远近采用合适的编码。由于前面提到的原因,32位系统中很少出现传输。因为有足够的线性空空间,所以一个程序很少需要两个代码段,甚至使用的系统模块都映射到同一个地址空。

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

jmp 8 e 347d 60;直接寻址段内跳转
jmp EBX;寄存器的间接寻址:仅段内跳转
jmp dword ptr[EBX];间接内存寻址,段内跳转
jmp dword ptr[00903 dec];同上
jmp前进ptr[00903 df 0];间接内存寻址、段间跳转

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

存储器被连续存储。如何确定取多少作为目标地址?Ordptr表示有效地址表示双字,所以
0059827C取为段内跳转。反之,fward ptr表示后面的有效地址指向48位全地址,所以取19F:658501A7作为远跳。

注意:在保护模式下,如果段间转移涉及到优先级的改变,会有一系列复杂的保护检查,现在可以忽略。以后技术提高了就可以自学了。

条件分支指令jxx:只能进行段内分支,只支持直接寻址。

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

Call的寻址方式与jmp相同,但是为了从子例程返回,这条指令会在跳转之前将紧随其后的下一条指令的地址推送到堆栈上。如果是段内调用(目标地址是32位偏移量),推送只是一个偏移量。如果是段间调用(目标地址是48位全地址),也按下一条指令的全地址。同样,如果段间转移涉及到优先级的改变,还有一系列复杂的保护检查。

且从子例程返回相应retn/retf指令。它从堆栈中获取返回地址(由call指令推送),并跳转到该地址执行。n取32位偏移量用于段内返回,retn取48位全地址用于段间返回。Retn/f也可以作为带立即数的操作数,实际上是从堆栈上传到子程序的参数个数(以字为单位)。数字返回后,堆栈指针esp自动加上指定的数字*2,从而丢弃堆栈中的参数。这里的具体细节留到下一篇。

虽然call和ret是设计来协同工作的,但是两者之间并没有必然的联系。也就是你用push指令直接把一个数压入堆栈,然后执行ret,他也会把你压入的数作为返回地址,跳转到那里执行。这种异常的进程转移可以作为反跟踪的方法。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » 汇编语言的准备知识

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情