回 帖 发 新 帖 刷新版面

主题:汇编语言的准备知识(2)

汇编语言的准备知识--给初次接触汇编者(2)

汇编指令的操作数可以是内存中的数据, 如何让程序从内存中正确取得所需要的数据就是对内存的寻址.

INTEL 的CPU 可以工作在两种寻址模式:实模式和保护模式. 前者已经过时,就不讲了, WINDOWS 现在是32位保护模式的系统, PE 文件就基本是运行在一个32位线性地址空间, 所以这里就只介绍32位线性空间的寻址方式.

其实线性地址的概念是很直观的, 就想象一系列字节排成一长队,第一个字节编号为0, 第二个编号位1, .... 一直到4294967295(十六进制FFFFFFFF,这是32位二进制数所能表达的最大值了). 这已经有4GB的容量! 足够容纳一个程序所有的代码和数据. 当然, 这并不表示你的机器有那么多内存. 物理内存的管理和分配是很复杂的内容, 初学者不必在意, 总之, 从程序本身的角度看, 就好象是在那么大的内存中.

在INTEL系统中, 内存地址总是由"段选择符:有效地址"的方式给出.段选择符(SELECTOR)存放在某一个段寄存器中, 有效地址则可由不同的方式给出. 段选择符通过检索段描述符确定段的起始地址, 长度(又称段限制), 粒度, 存取权限, 访问性质等. 先不用深究这些, 只要知道段选择符可以确定段的性质就行了. 一旦由选择符确定了段, 有效地址相对于段的基地址开始算. 比如由选择符1A7选择的数据段, 其基地址是400000, 把1A7 装入DS中, 就确定使用该数据段. DS:0 就指向线性地址400000. DS:1F5278 就指向线性地址5E5278. 我们在一般情况下, 看不到也不需要看到段的起始地址, 只需要关心在该段中的有效地址就行了. 在32位系统中, 有效地址也是由32位数字表示, 就是说, 只要有一个段就足以涵盖4GB线性地址空间, 为什么还要有不同的段选择符呢? 正如前面所说的, 这是为了对数据进行不同性质的访问. 非法的访问将产生异常中断, 而这正是保护模式的核心内容, 是构造优先级和多任务系统的基础. 这里有涉及到很多深层的东西, 初学者先可不必理会.

有效地址的计算方式是: 基址+间址*比例因子+偏移量. 这些量都是指段内的相对于段起始地址的量度, 和段的起始地址没有关系. 比如, 基址=100000, 间址=400, 比例因子=4, 偏移量=20000, 则有效地址为:

100000+400*4+20000=100000+1000+20000=121000. 对应的线性地址是400000+121000=521000. (注意, 都是十六进制数).

基址可以放在任何32位通用寄存器中, 间址也可以放在除ESP外的任何一个通用寄存器中. 比例因子可以是1, 2, 4 或8. 偏移量是立即数. 如: [EBP+EDX*8+200]就是一个有效的有效地址表达式. 当然, 多数情况下用不着这么复杂, 间址,比例因子和偏移量不一定要出现.

内存的基本单位是字节(BYTE). 每个字节是8个二进制位, 所以每个字节能表示的最大的数是11111111, 即十进制的255. 一般来说, 用十六进制比较方便, 因为每4个二进制位刚好等于1个十六进制位, 11111111b = 0xFF. 内存中的字节是连续存放的, 两个字节构成一个字(WORD), 两个字构成一个双字(DWORD). 在INTEL架构中, 采用small endian格式, 即在内存中,高位字节在低位字节后面. 举例说明:十六进制数803E7D0C, 每两位是一个字节, 在内存中的形式是: 0C 7D 3E 80. 在32位寄存器中则是正常形式,如在EAX就是803E7D0C. 当我们的形式地址指向这个数的时候,实际上是指向第一个字节,即0C. 我们可以指定访问长度是字节, 字或者双字. 假设DS[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]EDX]指向第一个字节0C:

mov AL, byte ptr DS[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]EDX] ;把字节0C存入AL
mov AX, word ptr DS[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]EDX] ;把字7D0C存入AX
mov EAX, dword ptr DS[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]EDX] ;把双字803E7D0C存入EAX

在段的属性中,有一个就是缺省访问宽度.如果缺省访问宽度为双字(在32位系统中经常如此),那么要进行字节或字的访问,就必须用byte/word ptr显式地指明.

缺省段选择:如果指令中只有作为段内偏移的有效地址,而没有指明在哪一个段里的时候,有如下规则:

如果用ebp和esp作为基址或间址,则认为是在SS确定的段中;
其他情况,都认为是在DS确定的段中。

如果想打破这个规则,就必须使用段超越前缀。举例如下:

mov eax, dword ptr [edx] ;缺省使用DS,把DS[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]EDX]指向的双字送入eax
mov ebx, dword ptr ES[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]EDX] ;使用ES:段超越前缀,把ES[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]EDX]指向的双字送入ebx

堆栈:

堆栈是一种数据结构,严格地应该叫做“栈”。“堆”是另一种类似但不同的结构。SS 和 ESP 是INTEL对栈这种数据结构的硬件支持。push/pop指令是专门针对栈结构的特定操作。SS指定一个段为栈段,ESP则指出当前的栈顶。push xxx 指令作如下操作:

把ESP的值减去4;
把xxx存入SS[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]ESP]指向的内存单元。

这样,esp的值减小了4,并且SS[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]ESP]指向新压入的xxx. 所以栈是“倒着长”的,从高地址向低地址方向扩展。pop yyy 指令做相反的操作,把SS[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]ESP]指向的双字送到yyy指定的寄存器或内存单元,然后把esp的值加上4。这时,认为该值已被弹出,不再在栈上了,因为它虽然还暂时存在在原来的栈顶位置,但下一个push操作就会把它覆盖。因此,在栈段中地址低于esp的内存单元中的数据均被认为是未定义的。

最后,有一个要注意的事实是,汇编语言是面向机器的,指令和机器码基本上是一一对应的,所以它们的实现取决于硬件.有些看似合理的指令实际上是不存在的,比如:

mov DS[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]edx], ds[IMG]http://www.netxeyes.org/image/bbs3000/angel_smile.gif[/IMG]ecx] ;内存单元之间不能直接传送
mov DS, 1A7 ;段寄存器不能直接由立即数赋值
mov EIP, 3D4E7 ;不能对指令指针直接操作.

回复列表 (共80个回复)

21 楼

有人问学16  位的汇编有没有用,当然有用了而且是非常的有用如今汇编用得更多的是在智能系统上而不是PC上你家里的各种电器如冰箱彩电等等都广泛地用了小型智能芯片它们的智能化主要是通过汇编来实现各种功能,对于小芯片一般都是用汇编来进行功能实现

INTEL早期的芯片是8086 和  8088,  后来的80286,是对前者的功能扩充至于再后来的386,486,奔腾,等芯片在原理和技术上都很好地继承了16位的8086,8088。

所以我觉得先学好16 位然后再学更高级的32,64  位就更容易了。而且16位汇编本来在PC外很多方面都有极为广泛的应用。

22 楼

楼主讲的好象都是一些关于寻址 的知识,有那位仁兄有关于多媒体,网络以及关于汇编和C/C++混合的发到论坛上供大家参考以下

23 楼

好多专有名词都不明白!

24 楼

请问汇编能干什么呀

25 楼

为什么我学的汇编 学校给提供的是本校老师出的垃圾样的书 课也没上完就考试 N简单的题目 就跟考傻子样的 汗 我自己看 有的东西都摸不到头 救救我吧

26 楼

[em1][em1][size=6]9[/size][color=FF00FF][/color]你 好好学呀

27 楼

<I>原来这就是汇编语言啊</I>[em8]

28 楼

我也学的是这个版的,觉得好难,看了教程好像懂了点,谢谢了!

29 楼

怎么我们都学的是16位的啊,呵呵呵呵呵呵!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      有什么问题一起讨论啊!!!!!!!!!!!!!!!!!!!!

30 楼

小弟学期作业 题目:
[size=5]数据区中有2个5字节无符号数“D1”和“D2”相加后放入“D3”中,由于相加后可能回有进位 “D3”的定义为6个字节数[/size]

请汇编高手帮小弟我  小弟我跪谢了~~~~~~~~
请大家可怜我吧~~~~~~~~
小弟不胜感激~~~~~~~~`
请汇编高手帮我用汇编程序做做这个题目~~~~~~~~~~~`

我来回复

您尚未登录,请登录后再回复。点此登录或注册