| 网站首页 | 文章中心 | 电子书下载 | 矢量图库 | 视频教程 | 素材下载 | 程序代码下载 | JS代码 | 论坛 | 
常用软件类:
|杀毒安全 |联络聊天 |网络软件 |多媒体类 |系统工具 |图形图像 |系统工具 |应用软件 |行业软件
开发设计类:
|动画制作 |图像处理 |3D设计 |操作系统 |站长学院 |网络相关 |WEB设计 |数据库类 |程序开发
简明x86汇编语言教程(3)使用寄存器
作者:佚名    文章来源:网络    点击数:    更新时间:2006-12-9
 

在前一节中的x86基本寄存器的介绍,对于一个汇编语言编程人员来说是不可或缺的。现在你知道,寄存器是处理器内部的一些保存数据的存储单元。仅仅了解这些是不足以写出一个可用的汇编语言程序的,但你已经可以大致读懂一般汇编语言程序了(不必惊讶,因为汇编语言的祝记符和英文单词非常接近),因为你已经了解了关于基本寄存器的绝大多数知识。

在正式引入第一个汇编语言程序之前,我粗略地介绍一下汇编语言中不同进制整数的表示方法。如果你不了解十进制以外的其他进制,请把鼠标移动到 这里 。


  汇编语言中的整数常量表示
  • 十进制整数
    这是汇编器默认的数制。直接用我们熟悉的表示方式表示即可。例如,1234表示十进制的1234。不过,如果你指定了使用其他数制,或者有凡事都进行完整定义的小爱好,也可以写成[十进制数]d或[十进制数]D的形式。
  • 十六进制数
    这是汇编程序中最常用的数制,我个人比较偏爱使用十六进制表示数据,至于为什么,以后我会作说明。十六进制数表示为0[十六进制数]h或0[十六进制数]H,其中,如果十六进制数的第一位是数字,则开头的0可以省略。例如,7fffh, 0ffffh,等等。
  • 二进制数
    这也是一种常用的数制。二进制数表示为[二进制数]b或[二进制数]B。一般程序中用二进制数表示掩码(mask code)等数据非常的直观,但需要些很长的数据(4位二进制数相当于一位十六进制数)。例如,1010110b。
  • 八进制数
    八进制数现在已经不是很常用了(确实还在用,一个典型的例子是Unix的文件属性)。八进制数的形式是[八进制数]q、[八进制数]Q、[八进制数]o、[八进制数]O。例如,777Q。

需要说明的是,这些方法是针对宏汇编器(例如,MASM、TASM、NASM)说的,调试器默认使用十六进制表示整数,并且不需要特别的声明(例如,在调试器中直接用FFFF表示十进制的65535,用10表示十进制的16)。

现在我们来写一小段汇编程序,修改EAX、EBX、ECX、EDX的数值。

我们假定程序执行之前,寄存器中的数值是全0:

? X
H L
EAX 0000 00 00
EBX 0000 00 00
ECX 0000 00 00
EDX 0000 00 00

正如前面提到的,EAX的高16bit是没有办法直接访问的,而AX对应它的低16bit,AH、AL分别对应AX的高、低8bit。

mov eax, 012345678h
mov ebx, 0abcdeffeh
mov ecx, 1
mov edx, 2
; 将012345678h送入eax
; 将0abcdeffeh送入ebx
; 将000000001h送入ecx
; 将000000002h送入edx

则执行上述程序段之后,寄存器的内容变为:

? X
H L
EAX 1234 56 78
EBX abcd ef fe
ECX 0000 00 01
EDX 0000 00 02

那么,你已经了解了mov这个指令(mov是move的缩写)的一种用法。它可以将数送到寄存器中。我们来看看下面的代码:

mov eax, ebx
mov ecx, edx
; ebx内容送入eax
; edx内容送入ecx

则寄存器内容变为:

? X
H L
EAX abcd ef fe
EBX abcd ef fe
ECX 0000 00 02
EDX 0000 00 02

我们可以看到,“move”之后,数据依然保存在原来的寄存器中。不妨把mov指令理解为“送入”,或“装入”。

练习题

把寄存器恢复成都为全0的状态,然后执行下面的代码:

mov eax, 0a1234h
mov bx, ax
mov ah, bl
mov al, bh
; 将0a1234h送入eax
; 将ax的内容送入bx
; 将bl内容送入ah
; 将bh内容送入al

思考:此时,EAX的内容将是多少?[ 答案 ]

下面我们将介绍一些指令。在介绍指令之前,我们约定:


   使用Intel文档中的寄存器表示方式

  • reg32 32-bit寄存器(表示EAX、EBX等)
  • reg16 16-bit寄存器(在32位处理器中,这AX、BX等)
  • reg8 8-bit寄存器(表示AL、BH等)
  • imm32 32-bit立即数(可以理解为常数)
  • imm16 16-bit立即数
  • imm8 8-bit立即数

在寄存器中载入另一寄存器,或立即数的值:

mov reg32, (reg32 | imm8 | imm16 | imm32)
mov reg32, (reg16 | imm8 | imm16)
mov reg8, (reg8 | imm8)

例如,mov eax, 010h表示,在eax中载入00000010h。需要注意的是,如果你希望在寄存器中装入0,则有一种更快的方法,在后面我们将提到。

交换寄存器的内容:

xchg reg32, reg32
xchg reg16, reg16
xchg reg8, reg8

例如,xchg ebx, ecx,则ebx与ecx的数值将被交换。由于系统提供了这个指令,因此,采用其他方法交换时,速度将会较慢,并需要占用更多的存储空间,编程时要避免这种情况,即,尽量利用系统提供的指令,因为多数情况下,这意味着更小、更快的代码,同时也杜绝了错误(如果说Intel的CPU在交换寄存器内容的时候也会出错,那么它就不用卖CPU了。而对于你来说,检查一行代码的正确性也显然比检查更多代码的正确性要容易)刚才的习题的程序用下面的代码将更有效:

mov eax, 0a1234h
mov bx, ax
xchg ah, al
; 将0a1234h送入eax
; 将ax内容送入bx
; 交换ah, al的内容

递增或递减寄存器的值:

inc reg(8,16,32)
dec reg(8,16,32)

这两个指令往往用于循环中对指针的操作。需要说明的是,某些时候我们有更好的方法来处理循环,例如使用loop指令,或rep前缀。这些将在后面的章节中介绍。

[1] [2] 下一页


相关文章