汇编笔记,指令用法,寄存器功能
CS是代码段寄存器,IP是指令指针寄存器。
mov指令被称为传送指令。
mov指令不能设置CS和IP的值。
要让CPU执行我们放在代码段中的指令,必须要将CS:IP指向所定义的代码段中的第一条指令的首地址。
8086CPU的工作过程:
1.从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器。
2.IP指向下一条指令。
3.执行指令。
push_段寄存器 将一个段寄存器中的数据入栈。
pop_段寄存器 出栈,用一个段寄存器接收出栈的数据。
push_内存单元 将一个内存字单元出的字入栈(栈操作都是以字为单位)
pop_内存单元 出栈,用一个内存字单元接收出栈的数据。
push指令:先改变SP,后向SS:SP处传送。
pop指令:先读取SS:SP处的数据,后改变SP。
对于标记数据段,要将它的段地址放在DS中。
对于代码段,要将它的段地址放在CS中,将段中的第一条指令的偏移地址放在IP中。
对于栈段,将它的段地址放在SS中,将栈顶单元的偏移地址放在SP中。
伪指令:
XXX segment
:
:
XXX ends
segment和ends是一对成对使用的伪指令。
例:
codesg segment 定义一个段,段名为“codesg”,这个段从此开始。
:
codesg ends 名为“codesg”的段到此结束。
end 是一个汇编程序总的结束标记,区别于ends,ends是一个段的结束标志。
assume 的含义为“假设”。
假设某一个段寄存器和程序中的某一个用segment…ends定义的段相关联。
格式:assume cs:codesg
伪指令由编译器处理。
loop指令:循环
inc bx 表示bx中的内容加一。
loop指令的格式:loop 标号
执行两步操作:
1.(cx)=(cx)-1
2.判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。
例:
mov cx,11
s:add ax,ax
loop s
可以显示的给出[ ]的段寄存器:
例:
mov al,[0]与mov al,ds:[0]的含义一样。
dw 即 “define word”。含义是定义字型数据。
end可以通知编译器程序的入口在什么地方。
编写一个程序,把数据、栈和代码放到不同的段中(使用assume、dw、start、segment、ends、end…)
assume cs:code,ds:data,ss:stack
data segment
dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h
data ends
stack segment
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0(十六个字节)
stack ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,20h
mov ax,data
mov ds,ax
mov bx,0
mov cx,8
s: push [bx]
add bx,2
loop s
mov bx,0
mov cx,8
s0: pop [bx]
add bx,2
loop s0
mov ax,4c00h
int 21h
code ends
end start
段名代表段地址。
and指令:逻辑“与”指令,按位进行“与”运算。
or指令:逻辑“或”指令,按位进行“或”运算。
凡是’…'这样的数据都是以字符形式给出的,编译器将把它们转化为相应的ASCII码。
db ‘unIX’ 相当于 db 75H,6EH,49H,58H 。
字母ASCII的二进制除第五位的数字不同外,其他的都一样,大写是0,小写是1。
si和di是8086CPU中和bx功能相近的寄存器,但是si和di不能够分成两个8位寄存器。
数据处理的两个基本问题:
1.处理的数据在什么地方?
2.要处理的数据有多长。
(reg表示一个寄存器,serg表示一个段寄存器)
reg的集合包括:ax、bx、cx、dx、ah、al、bh、bl、ch、cl、dh、dl、sp、bp、si、di。
sreg的集合包括:ds、ss、cs、es。
只有bx、si、di、bp这四个寄存器可以用在[…]中来进行内存单元的寻址。
他们可以单个出现,或者以bx和si、bx和di、bp和si、bp和di这四种组合出现。
立即数(idata)
要想知道指令要处理的数据有多长:
在有寄存器的情况下,通过寄存器名指明要处理的数据的尺寸:
如用ax等传递就表示指令进行的是字操作。
用al等指令就表示指令进行的是字节操作。
如果在没有寄存器的情况下,则用操作符X ptr指明内存单元的长度。(X可以为word或byte)
mov word ptr ds:[0],1表示指令访问内存单元是一个字单元。
byte ptr则表示指令访问的内存单元是一个字节单元。
push指令只进行字操作。
div是除法指令,注意:
1.除数:有8位和16位两种,在一个reg或内存单元中。
2.被除数:默认放在AX 或 DX和AX中,如果除数为8位,被除数则为16位,
默认在AX中存放;如果除数为16位,被除数则为32位,在DX和AX中存放,DX存放高16位,AX存放低16位。
3.商:如果除数为8位,则AL存储除法操作的商,AH存储除法操作的余数;
如果除数为16位,则AX存储除法操作的商,DX存储除法操作的余数。
被除数为32位,除数应为16位。
db、dw和dd:
db定义的数据占一个字节。
dw定义的数据占一个字。
dd定义的数据占两个字。
dup指令:
db 3 dup(0)相当于db 0,0,0
db 3 dup(0,1,2)相当于db 0,1,2,0,1,2,0,1,2
格式:
db(dw或dd)重复次数 dup(重复的类型数据)
转移指令:可以修改IP,或同时修改CS和IP的指令统称为转移指令。
offset操作符的功能时取得标号的偏移地址。
jmp指令要给出的两种信息:
1.转移的目的地址
2.转移的距离(段间转移、段内短转移、段内近转移)
jmp short 称号(转到称号处执行指令)(段内短转移)(IP修改范围为-128~127)
转移地址在内存中的jmp指令:
两种格式:
1.jmp word ptr 内存单元地址(段内转移)
功能:从内存单元地址处开始存放一个字,是转移的目的偏移地址。
2.jmp dword ptr 内存单元地址(段间转移)
功能:从内存单元地址处开始存放这两个字,高地址处的字是转移的目的段地址,低地址处是转移的目的偏移地址。
jcxz指令时有条件的转移指令,是短转移对IP的修改范围为:-128~127。
ret和retf:
ret指令用栈中的数据,修改IP的内容,从而实现近转移;
retf指令用栈中的数据,修改CS和IP的内容,从而实现远转移。
CPU执行ret指令时,进行下面两步操作:
(1)(IP)=((ss)*16+(sp))
(2)(sp)=(sp)+2
CPU执行retf指令时进行下面四步操作:
(1)(IP)=((ss)*16+(sp))
(2)(sp)=(sp)+2
(3)(CS)=((ss)*16+(sp))
(4)(sp)=(sp)+2
call指令:
CPU执行call指令时,进行两步操作:
(1)将当前的IP或CS和IP压入栈中;
(2)转移。
call指令不能实现短转移,其余和jmp指令原理相同。
mul指令:
mul指令时乘法指令,注意两点:
(1)两个相乘的数:要么都是8位,要么都是16位。如果是8位,一个默认放在AL中,另一个放在8位的reg或内存字节单元中;如果是16位,一个默认在AX中,另一个放在16位reg或者内存字单元中。
(2)积:如果是8位乘数,结果默认放在AX中;如果是16位乘数,结果高位默认在DX中存放,低位在AX中存放。
标志寄存器:
(1)用来存储相关指令的某些执行结果。
(2)用来为CPU执行相关指令提供行为依据。
(3)用来控制CPU的相关工作方式。
简称“flag”。
flag的1、3、5、12、13、14、15位在8086CPU中没有使用。
0、2、4、6、7、8、9、10、11位都有特殊意义。(CF、PF、ZF、SF、OF、DF等)
flag的第六位是ZF,零标志位。他记录相关指令执行后,如果结果为零,那么ZF=1,如果不为零,那么ZF=0.
flag的第二位是PF,奇偶标志位。他记录相关指令执行后,
其结果的所有bit位中1的个数是否位偶数。如果1的个数为偶数,PF=1,如果为奇数,那么PF=0。(看bit,也就是二进制)
flag的第7位是SF,符号标志位,他记录相关指令执行后,如果结果为负,SF=1,如果非负,SF=0.
flag的第0位是CF,进位标志位。在进行无符号数运算的时候,它记录了运算结果的最高有效位向更高位的进位值,或从更高位的借位值。
flag的第11位是OF,溢出标志位。如果有符号数运算结果发生溢出,OF=1;如果没有,OF=0.
标志寄存器的一些指令:
adc是带进位加法指令,它利用了CF位上记录的进位值。
指令格式:adc 操作对象1 操作对象2
功能:操作对象1= 操作对象1+操作对象2+CF
sbb是带借位减法指令,它利用了CF位上记录的借位值。
指令格式:sbb 操作对象1 操作对象2
功能:操作对象1=操作对象1-操作对象2=CF
cmp是比较指令,cmp的功能相当于减法指令,但不保存结果。
指令格式:cmp 操作对象1 操作对象2
功能:操作对象1-操作对象2但不保存结果,仅仅根据计算结果对标志寄存器进行设置。
如果因为溢出导致了实际结果为负,那么逻辑上真正的结果必然为正。
如果因为溢出导致了实际结果为正,那么逻辑上真正的结果必然为负。
和cmp配对的条件跳转符:
指令 含义 检测的相关标志位
je 等于则转移 zf=1
jne 不等于则转移 zf=0
jb 低于则转移 cf=0
jnb 不低于则转移 cf=0
ja 高于则转移 cf=0且zf=0
jna 不高于则转移 cf=1或zf=1
j:jump e:equal ne:not equal b:below a:above
flag的第10位是DF,方向标志位。在串处理指令中,控制每次操作后si、di的增减。
df=0 每次操作后si、di递增;
df=1 每次操作后so、di递减。
串传送指令:movsb
格式:movsb
功能:执行movsb指令相当于进行下面几步操作。
(1)((es)*16+(di))=((ds)*16+(si))
(2)如果df=0则:(si)=(si)+1 (di)=(di)+1 df=1就减一。
如果传送一个字为:movsw。
cld指令:将df设置为0
std指令:将df设置为1.
pushf:将标志寄存器的值压栈。
popf:把从栈中弹出的数据,送入寄存器中。
do0程序的主要任务是显示字符串。
中断:
int指令:系统调用,引发中断。
格式:int n,n为中断类型码。
功能:引发中断过程。
执行过程:
(1)取中断类型码n;
(2)标志寄存器如栈,IF=0,TF=0;
(3)CS、IP入栈;
(4)(IP)=(n4),(CS)=(n4+2)
从此处转去执行n号中断的中断处理程序。
端口:
对端口进行读写时,端口号放在dx中。
端口用in和out进行读写。
shi和shr是逻辑移位指令。
shl是逻辑左移指令,功能:
(1)将一个寄存器或内存单元中的数据向左移位;
(2)将最后移出的一位写入CF中;
(3)最低位用0补充。
同理shr是右移。
栈传递:
用栈传递参数:ret n的含义:
pop ip
add sp,n