您的位置:首页 > 编程语言

汇编程序基础知识要点

2009-05-16 19:59 267 查看
汇编程序基础知识要点:

汇编程序由汇编指令、伪指令、标号组成

汇编指令是cpu真正要执行的代码

伪指令不是用于被cpu执行的代码,而是用于被编译器识别的特殊指令,比如end告诉编译器汇编程序到此为止,start告诉编译器程序的第一条

指令从这里开始

标号实际上是地址的一种表示,表明了某一个段的起始地址

80x86cpu通用寄存器:ax,bx,cx,dx

段寄存器:ds,cs,ss,es

特殊寄存器:ip,sp

其他的寄存器:si,di,bp,标志位寄存器

word类型数据存放在内存中时,高位存放在高字节,地位存放在低字节

如:1234H

2000:34H

2001:12H

bx中默认存放数据段偏移地址

bp和bx类似,但是bp的默认段地址在ss中

ds中默认存放内存基地址

cs中存放cpu执行的机器指令的段地址

ip中存放cpu执行的机器指令的偏移地址

ss中存放程序的栈基地址

sp中存放栈顶的偏移地址

cx中存放loop循环的次数

ax是add运算的默认结果存放地址

si和di是和bx相似的寄存器,他们都默认存放数据段的偏移地址,

但是si和di不能被分成两个字节的寄存器使用

注意点:

[bx+100]可以写成:100[bx] 或 [100+bx] 或 [bx].200

[bx+si]可以写成:[bx][si]

[bx+si+idata] idata[bx+si] idata[bx][si] [bx+si].idata [bx][si].idata

在80x86cpu中只有四个寄存器可以用于如[..]的内存寻址,它们是bx,si,di,bp

在[..]中只有四种组合是合法的分别是:[bx+si],[bx+di],[bp+si],[bp+di]

80x86cpu可以处理两种尺寸的数据,分别是byte和word,在汇编指令中需要指明要处理的数据是byte还是word。通常的方法是:

1.通过指令中的寄存器来表明,比如:mov ax,[bx+0]

mov al,[bp+2]

2.如果指令中没有寄存器,或寄存器无法表明当前要操作的数据的长度类型,需要用

X ptr来标明数据的长度,这里的x指byte 或 word

如:

inc byte ptr [bx]

mov word ptr [bx], 1000h

3.有些指令默认了访问的数据类型,比如push指令只能访问word类型数据

转移指令分为:段内转移指令、段间转移指令

段内转移指令又分为:段内短转移、段内近转移

jmp 标号地址:

jmp short 标号 段内短转移

jmp near ptr 标号 段内近转移

jmp far ptr 标号 段间转移

jmp 寄存器:略 段内转移

jmp 内存单元:

jmp dword ptr [bx] 段间转移

jmp word ptr [bp] 段内转移

loop循环指令是跳转指令,并且是段内短转移指令

所有的有条件转移指令都是段内段转移指令,比如jcxz有条件转移指令,含义是:

如果cx==0则跳转到标号处,那么跳转的偏移量(或者说距离)是:

标号的地址-jcxz指令的下一条指令地址

ret是转移指令,他可以实现段内近转移和段间转移,它的实现原理是:

从栈中弹出ip 或ip和cs,注意当实现段间转移时,先从栈中弹出的是ip然后cs

call是转移指令,它不能实现短转移它的实现原理:

将当前ip或ip和cs压入栈中,再执行跳转到标号处的操作

cpu的标志寄存器:

进位是指无符号数运算时最高位进位或借位

溢出是指有符号数的运算中产生无法表达的情况

指令部分:

div xxx

div除法操作的被除数默认放在ax或dx和ax中。

当除数是8位时,被除数是16位,被除数放在ax中,运算的结果存放在al中,余数存放在ah中。

当除数是16位时,被除数是32位,被除数放在dx和ax中,其中dx中存放的是被除数的高16位,ax中存放的是被除数的低16位

而运算的结果存放在ax中,余数存放在dx中

adc和sbb都是带CF的运算操作,之所以使用这种带进位的运算操作,主要是为了解决大数的加减法操作。

如:假设使用的cpu是8086 8088 80286,那么cpu中只有16位的寄存器,当处理16位的加减法运算时直接

将操作数放置于一个寄存器中即可,当处理32位的加减法时可以用一个寄存器放置32位的低16位(ax),

用另一个寄存器放置32位的高16位(dx),但是当低16位的相加减出现进位或借位时,如果没有adc或

sbb我们需要如下来处理:

add ax, [bx] ;ax和[bx]中存放低16位

add dx, [bx+2] ;dx和[bx+2]中存放高16位

add dx, CF ;当然这里要取得CF需要进一步处理

如果使用了adc,则可以取消上面的第三步

add ax, [bx]

adc dx, [bx+2]

同样的,但处理减法操作时,遇到借位不用sbb时,需要我们对高16的操作结果减去CF

db dw dd都是伪指令,分别是定义byte, word, double world

dup 重复次数 (重复的数据)

cmp指令实际上就是做了减法操作,但是操作的结果并没有保存在cpu或内存中。

cmp指令虽然不会将操作的结果放在任何地方,但是cmp的结果会影响标志寄存器。

比如:比较两个无符号数 cmp ax, bx

如果ax < bx 则标志寄存器的zf=0 cf=1

cmp不仅可以比较无符号数,还可以比较有符号数,但比较有符号数时

sf 和 of 的值要特别注意:

sf=1并不表示ax < bx因为可能在作减法操作的时候发生了溢出的情况,这时

说明真正的操作结果应该是ax-bx>0,由于发生了溢出的情况所以才导致结果为负。

所以对有符号数的比较时要特别注意of的值

sf=0, of=0 没有溢出,所以减法的操作结果是正确的,说明ax>bx

sf=0, of=1 有溢出,所以减法的操作结果是错误的,结果应该是负的,ax<bx

sf=1, of=0 没有溢出,所以减法的操作是正确的,说明ax<bx

sf=1, of=1 有溢出,所以减法的操作是错误的,结果应该是正的,ax>bx

je:jump if equal zf=1

jne:jump if not equal zf=0

ja:jump if above cf=0且zf=0

jna:jump if not above cf=1或zf=0

jb:jump if below cf=1

jnb:jump if not below cf=0

movsb/movsw是串传送操作

es:di指向目的地址

ds:si指向源地址

DF标志位表示了传送的方向:即传送一次之后,di和si是+还是-

如果DF=0则是+ 如果DF=1则是-

cld和std专门用于设置DF标志位,cld将DF设为0,std将DF设为1

通常movsb或movsw与rep联合使用

rep的作用相当于loop

如:rep movsb

pushf:是将标志位寄存器压入栈中

popf:是将弹出标志位寄存器

其他:

shl eax, n 逻辑左移

shr eax, n 逻辑右移

org 07c00 将代码加载到7c00处
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: