网页功能: 加入收藏 设为首页 网站搜索  
INTEL X86 体系 32 位汇编语言速成
发表日期:2006-08-28作者:[转贴] 出处:  

  上回为大家简单介绍了 Visual C++ Inline Assembly,相信已经有人想实际动手来试试了。然而,要想自由使用 Inline Assembly,你首先必须掌握 INTEL X86 体系的 32 位汇编语言。本文正是为那些已经略有 8086 汇编语言基础却没接触过 X86 体系的 32 位汇编语言的同志们准备的。我们将一起了解和深入 INTEL X86 体系的 32 位汇编语言。

  因为我们的目标是“速成”,如果你能有点基础的话,那么在此之上展开讨论就能让彼此都感觉轻松很多。假若你以前完全没有学习过汇编语言,那么请务必先去找本 8086 汇编语言的教科书来补习补习之后再来阅读本文。

  学习一种的汇编语言,必须了解这种 CPU 的寄存器、寻址方式以及各种指令。我们就先从寄存器开始着手吧。

g
INTEL X86 常用寄存器

通用寄存器 段寄存器

AH/AL AX (EAX) 累加器 CS 代码段
BH/BL BX (EBX) 基址 DS 数据段
CH/CL CX (ECX) 计数器 SS 堆栈段
DH/DL DX (EDX) 数据 ES 附加段
(FS) 386 新增的段寄存器
(Exx) 为 386 新增的 32 位寄存器 (GS) 386 新增的段寄存器


指针寄存器 堆栈寄存器

SI (ESI) 源索引指针 SP (ESP) 栈指针
DI (EDI) 目的索引指针 BP (EBP) 基址指针
IP 指令指针


状态寄存器

|11|10|F|E|D|C|B|A|9|8|7|6|5|4|3|2|1|0|
| | | | | | | | | | | | | | | | | +--- CF Carry Flag
| | | | | | | | | | | | | | | | +--- 1
| | | | | | | | | | | | | | | +--- PF Parity Flag
| | | | | | | | | | | | | | +--- 0
| | | | | | | | | | | | | +--- AF Auxiliary Flag
| | | | | | | | | | | | +--- 0
| | | | | | | | | | | +--- ZF Zero Flag
| | | | | | | | | | +--- SF Sign Flag
| | | | | | | | | +--- TF Trap Flag (Single Step)
| | | | | | | | +--- IF Interrupt Flag
| | | | | | | +--- DF Direction Flag
| | | | | | +--- OF Overflow flag
| | | | +----- IOPL I/O Privilege Level (286+ only)
| | | +----- NT Nested Task Flag (286+ only)
| | +----- 0
| +----- RF Resume Flag (386+ only)
+------ VM Virtual Mode Flag (386+ only)

  怎么样,看起来大半部分都应该是我们以前很熟的了吧。现在,我们只需要侃侃那些在 386 上才
开始出现的新的寄存器就行了。

  首先必须强调的是,在用 32 位汇编语言编程的时候,所有的地址偏移量都是 32 位的,在寻址时
千万不要还用原来的 16 位方式。

  对于通用寄存器来说,多了种形如 (Exx) 的 32 位寄存器,它的低 16 位内容就是原来的 16 位寄
存器,而多出的高 16 位的内容,则只能通过使用 32 位寄存器来访问。

  再以指针寄存器为例,在寻址时一定要用 ESI、EDI、EBP 等等,必须要把以前那种 mov ax,[si] 之
类的指令改为 mov ax,[ESI]。

  从 386 开始,多出了 FS、GS 这两个新的段寄存器。由于我们学习的目的是为了今后写在线汇编,所以很多繁琐的问题都不会直接遇到。为了能更快地投入实际运用,这里就不打算去讲述保护模式的细节了,而直接给大家提出一个结论,你只管按照这个结论去做就行了。

  这个简单的结论就是:你在 VC 中写在线汇编时,尽量不要去碰段寄存器!

  得出这个结论的第一个原因是 VC 生成的应用程序的 DS、ES 和 SS 是相同的。换种说法,整个应用程序的数据段、附加段、堆栈段都在同一个地址,你根本就没有去改变它们的必要。第二个原因是,因为是保护模式,每个段都有 4GB 大小,所有数据都可以轻易地放进去,于是当然就用不着去改段寄存器了。最后一个原因是,保护模式下的段寄存器使用方法同实模式下完全不一样,在你没弄懂以前,最好别去乱改,否则……嘿嘿,死掉了别怨我。

  至于状态寄存器,大家肯定是非常熟悉了,虽然多了几位,但这些内容我们一般都用不着,所以也可以略过。

  下面将开始讲述 INTEL X86 的 32 位偏移地址构成方式。

  这里给出关于 80386 寻址模式的一张列表:


基地址 + (变址 X 比例因子) + 偏移量

|无 | |无 |
|EAX| |EAX|
|EBX| |EBX| |1|
|ECX| |ECX| |2| | 无 |
|EDX| + |EDX| X |4| + | 8位|
|ESP| |---| |8| |32位|
|EBP| |EBP|
|ESI| |ESI|
|EDI| |EDI|

其中,“---”表示 ESP 不能被用作变址寄存器

  注意到比例因子,这个可是从 386 才开始加入的好东西,它对处理表结构大有好处,而且还衍生出了不少技巧,详情请参考《图形程序开发人员指南 (Michael Abrash's Graphics Programming Black Book
Special Edition)》一书第 6.3 节。

  在 80386 寻址时,其默认的段寄存器取决于所选择的基地址寄存器。如果基地址寄存器是 ESP 或
者 EBP,则默认的段寄存器是 SS。对于别的基地址寄存器的选择,包括无基地址寄存器,DS 仍然是其默认的段寄存器。其实,前面已经说了,你在 VC 中写在线汇编时,可以不去碰段寄存器,但反正已经讲到这里了,所以随便就提两句。

  其对应关系见下表:


基地址寄存器 默认的段寄存器

BP or SP SS
SI or DI DS
DI strings ES
SI strings DS

  了解了寄存器和寻址方式以后,我们就可以使用过去已经知道的指令开始编程了。但 INTEL 在 386 以后新增了不少指令,虽然这里我不可能全部列出来,但可以稍微看看其中比较常用的几条。


BSWAP - 字节交换 (486+)
颠倒 32 位寄存器的字节排列顺序。
CDQ - 双字转换成四字 (386+)
把 EAX 中的符号数按符号扩展为 EDX:EAX,即把 EAX 中的第 32 位赋予 EDX 的每一位。
CWDE - 将字扩展转换成双字 (386+)
把 AX 中的符号数按符号扩展为 EAX,即把 AX 中的第 16 位赋予 EAX 的高 16 位。
MOVSX - 符号扩展传送 (386+)
传送数据时先作符号扩展。
MOVZX - 零扩展传送 (386+)
传送数据时先作零扩展。
SHLD/SHRD - 双精度移位 (386+)
把源操作数中的若干位移入目的操作数,源操作数中的内容保持不变。
POPA/POPAD - 所有通用寄存器出栈 (80188+)
PUSHA/PUSHAD - 所有通用寄存器入栈 (80188+)

  怎么样?感觉这些指令挺爽的吧,其实还有很多的好东西(比如各种位处理指令等等)没能在这里提到。更完整和详细的资料请查阅『INTEL 汇编指令集』。

  到此为止,该了解的基础知识我们差不多都已经全部提到了,很简单不是?剩下的就是该你自己去多多编程实践了。只有这样,你才能获取宝贵的经验,从而真正地掌握这门汇编语言。

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 INTEL X86 体系 32 位汇编语言速成
本类热点文章
  SSE 介紹
  浮点数到整数的快速转换
  基于SSE指令集的程序设计简介
  CPU 的 cache 和 latency
  关键字 对齐 内存对齐
  INTEL 体系结构 MMX™ 技术开发者..
  在非MFC程序中使用调试宏 ASSERT(),VER..
  Microsoft Visual C++ 浮点优化
  INTEL X86 体系 32 位汇编语言速成
  加速&优化技术
  加快程序运行速度的技巧
  VC代码的编写和调试
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00377