汇编程序基础知识要点

汇编程序基础知识要点:

汇编程序由汇编指令、伪指令、标号组成
汇编指令是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处

你可能感兴趣的:(c,汇编,div,byte,编译器,X86)