汇编语言,当然,我们学习是在c语言的基础上,那么,我们就先复习一下c语言的知识
C语言的基础,进制转换必不可少
数组,函数……
接下来,我们学习了数据结构:顺序表,链表,排序,查找,队列……
那么,我们就正式开始学习汇编语言吧
寄存器分类:
通用寄存器:AX,BX,CX,DX
变址寄存器:SI,DI
指针寄存器:SP,BP
指令指针寄存器:IP
段寄存器:CS,SS,DS,ES
标志寄存器:PSW
目录
第一章基础知识
第二章寄存器
第三章寄存器(内存访问)
第四章第一个程序
第五章[BX]和loop指令
第六章包含多个段的程序
第七章更灵活的定位地址的方法
第八章数据处理的两个基本问题
第九章转移指令的原理
第十章CALL和RET指令
第十一章标志寄存器
第十二章内中断
第十三章int指令
第十四章端口
第十五章外中断
第十六章直接定址表
第十七章使用BIOS进行键盘输入和磁盘读写
第一章基础知识
内容:对硬件系统结构的问题进行一部分探究
知识点:
1.1机器语言和汇编语言
机器语言: 机器能识别的程序语言或指令代码,用二进制表示
汇编语言:用来定义计算机程序的形式语言,用来向计算机发出指令
机器语言是计算机能直接运行的语言,是二进制语言,属于低级语言;汇编语言是面向机器的低级语言,不能被机器直接识别,需要编译
1.2用汇编语言编写程序的工作过程:
1.3.存储单元
聊到存储单元,那么我们首先要了解到,一个二进制位是1bit,8bit=1byte,就是一个字节是8个bit,
1.4.总线
1.5.内存地址空间
第二章寄存器
2.1通用寄存器
注意:指令的两个对象位数一致
2.2段寄存器
内存没有分段,段的划分来自cpu
用一个段存放代码,叫“代码段”
用一个段存放数据,叫“数据段”
用一个段存放栈,叫“栈段”
2.3汇编指令
2.4物理地址
物理地址=段地址*16+偏移地址
2.5CS和IP
CS:IP
CS:代码段寄存器
IP:指令指针寄存器
8086cpu工作过程:
1.从CS:IP指向的内存单元读取指令,读取的指令进入指令爱冲器
2.IP=IP+所读取指令的长度,从而指向下一条指令
3.执行指令。转到步骤(1),重复这个过程
修改CS,IP
1. debug中修改:-r cs或者-r ip
2. 同时修改:jmp 段地址:偏移地址
3. 修改ip jmp 某一合法寄存器、
第三章寄存器(内存访问)
3.1内存中字的存储x
16位的字在内存中需要2个连续字节存储,存放方式如下:
3.2DS
DS寄存器:存放访问数据的段地址
mov bx,1000H 读取
mov ds,bx 放入
mov al,[0] 传送
上面三条指令将1000H(1000:0)中的数据读到al中
3.3mov,add,sub指令
mov 寄存器 数据
mov 寄存器 寄存器
mov 寄存器 内存单元
mov 内存单元 寄存器
mov 段寄存器 寄存器
mov 寄存器 段寄存器
add 寄存器 数据
add 寄存器 寄存器
add 寄存器 内存单元
add 内存单元 寄存器
sub 寄存器 数据
sub 寄存器 寄存器
sub 寄存器 内存单元
sub 内存单元 寄存器
注意:段寄存器只能mov。段寄存器是代码指令,相当于领导,领导不干活,负责指挥,干活的是数据段里的数据,向哪个方向干,用IP指方向,说白了就是移动内存位置的
3.4栈
栈是一种只能在一段进入插入或者删除的数据结构
如今的cpu中都有栈的设计(将内存当作栈)
3.5栈顶越界问题
1.当栈满的时候使用push指令入栈
2.当栈空的时候使用pop指令出栈
3.6push,pop指令
push 寄存器 将一个寄存器中的数据入栈
pop 寄存器 出栈,用一个寄存器接收出栈的数据
第四章第一个程序
4.1一个源程序从写出到执行的过程
1.编写汇编源程序
2.对源程序进行编译连接
3.执行可执行文件中的程序
文本编辑->源程序文件(.asm)->编译->目标文件(.obj)->连接->可执行文件(.exe)->运行程序
4.2源程序
第五章[BX]和loop指令
[...]--(汇编语法规定)表示一个内存单元
()--(为方便学习做出的约定)表示一个寄存器或一个内存单元中的内容
()里面的元素可以是寄存器名,段寄存器名,内存单元的物理地址(一个二十位的数据)
()里面表示的数据的类型可以是字节或字
mov ax,[0] 这个内存单元两个字节
mov al,[0] 这个内存单元一个字节
用[0]表示一个内存单元时,0表示单元的偏移地址,段地址默认在ds中,单元的长度(类型)可以由具体指令中的其他操作对象(比如寄存器)指出
5.1[BX]
mov ax,[BX]
功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将ax中的数据送入SA:EA中
5.2loop指令
操作过程:(cx)=(cx)-1
判断cx中的值,不为0则转至标号处执行程序,如果为0向下执行
loop指令实现循环功能,cx存放循环次数
5.3段前缀
用于显式地指明内存单元的段地址的
5.4一段安全的空间
如果我们需要向為在空回写入数据的话,要使用操作系统给我什众配的空间,而不应该直接的用地址任意指定内存单元
硬件已经被这些操作系统利用CPU保护模式所提供的功能全面而严格的管理了
如果0:200-0:2f单元的内容都是0的话,则证明DOS和共他合法的程序没有使用这里。
1)我们需要直接向一段内存中写入内容;
2)这段内存空间不应存放系统或其他程序的数据或代码,否则写入操作很可能引发错误
3)DOS方式下,一般情况,0:200-0:2f空间中没有系统或其他程序的数据或代码
4)以后,我们需要直接向一段内存中写入内容时,就使用0200-0-2 这段空间。
第六章包含多个段的程序
程序取得所需空间的方法:
在加载程序的时候为程序分配(通过在源程序中定义段来进行内存空间的获取)
程序在执行的过程中向系统申请
dw––定义一个字(16个字节)
db––定义一个字节
dd––定义一个双字
6.1在代码段中使用数据
单任务系统中,可执行文件中的程序执行过程:
由其他的程序(Debug、command或其他程序)将可执行文件中的程序加载入内存;
设置CS:IP指向程序的第一条要执行的指令(即程序的入口),从而使程序得以运行;
程序运行结束后,返回到加载者
6.2将数据,代码,栈放入不同的段
注意:
用data等命名,并不是让CPU去执行data段里的内容,这些名称和s,s0一样,仅仅在源程序中存在,CPU并不知道它们
assume cs:data,将cs与data段相连,并不代表cpu将cs指向data(assume是伪指令,是由编译器执行的,也是仅在源程子中存在的信息CPU并不知道它们。它将你定义的具有定用途的段和相关的寄存器联系起来)
第七章更灵活的定位地址的方法
7.1and和or指令
add指令:逻辑与指令,按位进行运算
or指令:逻辑与指令,按位进行运算
7.2ASCII码
按下键盘的a,在屏幕上显示的过程:
7.3以字符形式给出的数据
用'...'的方式指明数据是以字符的形式给出的,编译器将把他们转化为相应的ASCII码
7.4[bx+idata]
[bx+idata]表示一个内存单元,它的偏移地址
例子:mov ax,[bx+200]
将一个内存单元的内容送入ax,偏移地址为bx中的数值加上200
7.5SI和DI
7.6[bx+si]和[bx+di]
mov ax,[bx+si]=mov ax,[bx][si]
将一个内存单元的内容送入ax,偏移地址为bx中的数值加上si
7.7[bx+si+idata]和[bx+di+idata]
mov ax,[bx+si]
将一个内存单元的内容送入ax,偏移地址为bx中的数值加上si
7.8不同的寻址方式的灵活应用
(1)[idata]用一个常量来表示地址,可用于直接定位一个内存单元;
(2)[bx]用一个变量来表示内存地址,可用于间接定位一个内存单元:
(3)[bxtidata]用一个变量和常量表示地址,可在一个起始地址的基础上用变量间接定位一个内存单元;
(4)[bx+si]用两个变量表示地址;
(5)[bx+sitidata]用两个变量和一个常量表示地址。
第八章数据处理的两个基本问题
1.处理的数据在什么地方
2.要处理的数据有多长
8.1bx,si,di,bp
只有这四个寄存器可以用在[...]中来进行内存单元的寻址(bx以外的通用寄存器,段寄存器不可以用在[...]中)
8.2机器指令处理的数据在什么地方
数据的位置:
1.立即数
对于直接包含在机器指令中的数据(执行前在CPU的指令缓冲器中),在汇编语言中称
为:立即数
2.寄存器
指令要处理的数据在寄存器中,在汇编指令中给出相应的寄存器名
3.段地址(SA)和偏移地址(EA)
指令要处理的数据在内存中,在汇编指令中可用[X]的格式给出EA,SA 在某个段寄
存器中。
8.3指令要处理的数据有多长
1.通过寄存器名指明要处理的数据的尺寸
bx,ax是字
al,bl是字节
2.在没有寄存器名存在的情况下,用操作符X ptr指明内存单元的长度,X在汇编指令中可以为word或byte
word ptr字单元
byte ptr字节单元
在没有寄在器参与的内存单元访间指令中,用word pt 或byte ptr显性地指明所要访问的内存单元的长度是很必要的。否则,CPU无法得知所要访问的单元是字单元,还是字节单元
3.其他方法
push指令只能进行字操作
8.4div指令(除法指令)
格式:
div reg(寄存器)
div 内存单元
8.5dup
dup是一个操作符,在汇编语言中同db,dw,dd等,也是由编译器识别处理的符号,与db,dw,dd配合使用,用来进行数据的重复
db 重复的次数 dup(重复的字节型数据)
dw 重复的次数 dup(重复的字型数据)
dd 重复的次数 dup(重复的双字型数据)
例子:
db 3 dup(0)定义3个字节,值都是0,相当于db 0,0,0
db 3 dup(0,1,2)定义9个字节,值是10,1,2,0,1,2,0,1,2,相当于db 0,1,2,0,1,2,0,1,2
db 3 dup(‘abc’,‘ABC')定义18个字节,值是abcABCabcABCabcABC,相当于db ’abcABCabcABCabcABC-‘
第九章转移指令的原理
背景:一般情况下指令是顺序地逐条执行的,而在实际中,常需要改变程序的执行流程
转移指令:
1.可以控制CPU执行内存中某处代码的指令
2.可以修改IP,或同时修改CS和IP的指令
8086的转移行为有以下几类。
只修改IP时,称为段内转移比如:jmpax。
同时修改CS和IP时,称为段间转移比如:jmp 1000:0。
由于转移指令对IP的修改范围不同段内转移又分为:短转移和近
短转移IP的修改范围为-128~127。
近转移IP的修改范围为-32768-32767。
8086CPU的转移指分为以下几类。
无条件转移指令(如:jmp)
条件转移指令
循环指令(如:loop)
过程
中断
9.1操作符offset
offset:由编译器处理的符号
功能:取得符号的偏移地址
start mov ax,offset start相当于mov ax,0
9.2jmp指令
jmp:无条件转移指令,可以只改变IP,也可以同时修改CS和IP
jmp指令要给出两种信息:
(1)转移的目的地址
(2)转移的距离(段间转移,段内短转移,段内近转移)
1.依据位移进行转移的jmp指令
引子:常见指令中的立即数均在机器指令中有体现
jmp short 标号(转到标号处执行指令)
8位位移=标号处的地址-jmp指令后的第一个字节的地址:
(2)short指明此处的位移为8位位移;
(3)8位位移的范围为-128-127,用补码表示
(4)8位位移由编译程序在编译时算出。
jmp near ptr标号 指明了相对于当前IP的转移位移
1)16位位移-标号处的地址jmp指令后的第一个字节的地址:
2)near ptr指明此处的位移为16位位移,进行的是段内近转移;
(3)16位位移的范围为-32768~32767,用补码表示;
(4)16位位移由编译程序在编译时算出。
问:jmp short指令中,转移到了哪里
:jmp short 的机器指令中,包含的是跳转到指令的相对位置,而不是指令的目标位置
CPU在执行jmp指令的时候并不需要转移到目的地址
CPU不需要这个目的地址就可以实现对IP的修改
jmp far ptr标号 实现的是段间转移(远转移)
(CS)=标号所在段的段地址
(IP)=标号在段中的偏移地址
far ptr指明了指令用标号的段地址和偏移地址修改CS和IP
2.转移地址在寄存器中的jmp指令
指令格式:jmp 16位reg
功能:IP=16位reg
3.转移地址在内存中的jmp指令
jmp word ptr
功能:从内存单元地址处开始存放着一个字》是转移的目的偏移地址。
内存单元地址可用寻址方式的任一格式给出
jmp dword ptr
功能:从内存单元地址处开始存放着两个字,高地址处的字是转移的目的段地as sume
地址处是转移的目的偏移地址。)
(CS)=(内存单元地址+2)
(IP)=(内存单元地址)
内存单元地址可用寻址方式的任一格式给出
9.3jcxz指令
jcxz指令:有条件转移指令,所有的有条件转移指令都是短指令,在对应的机器码中包含转移的位移,而不是目的地址。对IP的修改范围都为:-128~127。
指令格式:jcxz标号(好果(ex)=0.转移到标号处执行。
操作:当(Cx)=0时,(IP)=(IP)+8位位移:
8位位移一标号处的地址-jcxz指令后的第一个字节的地址;
8位位移的范围为-128-127,用补码表示;
8位位移由编译程序在编译时算出。
我们从jcxz的功能中可以看出,“jxz标号”的功能相当于:
if((cx)==0)jmp short标号;
9.4根据位移进行移位的意义
在它们对应的机器码中不包含转移的目的地址,而包含的是到目的地址的位移
1.如果loop s的机器码中包含的是s的地址,则就对程序段在内存中的偏移地址有了严格的限制,易引发错误
2.当机器码中包含的是转移的位移,无论s处指令的实际地址是多少,loop指令转移的相对位移是不变的
第十章CALL和RET指令
10.1ret和retf
ret指令:用栈中的数据,修改IP的内容,从而实现近距离 pop IP
retf指令: 用栈中的数据,修改CS和IP的内容,从而实现远距离 pop IP pop CS
10.2call指令
CPU执行call指令操作:
将当前的IP或CS和IP压入栈中
转移
call far ptr标号 实现的是段间转移
10.3mul指令
乘法指令
格式:
mul reg
mul 内存单元
10.4参数和结果传递的问题
子程序一般都要根据提供的参数处理一定的事务,处理后,将结果(返回值)提供给调用者
10.5寄存器冲突的问题
CX--既用于循环,又用于读取数据
(1)编写调用子程序的程序的时候不必关心子程序到底使用了哪些寄存器
(2)编写子程序的时候不必关心调用者使用了哪些寄存器:
(3)不会发生寄存器冲突。
解决这个问题的简捷方法是,在子程序的开始将子程序中所有用到的寄存器中的内容都保存起来,在子程序返回前再恢复。可以用栈来保存寄存器中的内容。
第十一章标志寄存器
PSW/FLAGS别称:程序状态字
作用:
用来存储相关指令的某些执行结果:
(2)用来为CPU执行相关指令提供行为依据:
(3)用来控制CPU的相关工作方式。
flag寄存器是按位起作用的,也就是说,它的每一位都有专门的含义,记录特定的信息
flag的1,3,5,12,13,14,15位在8086CPU中没有使用
11.1ZF标志
零标志位
它记录相关指令执行后,其结果是否为0.
0-- >zf=1
结果不为0-->zf=0
11.2PF标志
奇偶标志位
它记录相关指令执行后,其结果的所有bit位中1的个数是否为偶数(结果的所有二进制位中1的个数)
1的个数为偶数-- >pf=1
1的个数为奇数-- >pf=0
11.3SF标志
符号标志位
它记录相关指令执行后,其结果是否为负
结果为负-- >sf=1
结果非负-->sf=0
11.4CF标志
进位标志位
它记录无符号数运算结果的最高有效位向更高位的进位值,或从更高位的错位值
对于位数为N的无符号数来说,其对应的二进制信息的最高位,即第N-1位,就是add
它的最高有效位,而假想存在的第N位,就是相对于最高有效位的更高位。
11.5OF标志
在进行有符号数运算的时候,如结果超过了机器所能表示的范围称为溢出
溢出标志位
发生溢出OF=1
没有溢出OF=0
CF和OF的区别:
CF是无符号数运算有意义的标志位
OF是有符号数运算有意义的标志位
11.6adc标志
带进位加法指令,它利用了CF位上记录的进位值。
指令格式:adc操作对象1,操作对象2
功能:操作对象1=操作对象1+操作对象2+CF
比如指令adc ax,bx实现的功能是:(ax)-(ax)+(bx)+CF
11.7sbb标志
带借位减法指令,它利用了CF位上记录的借位值
指令格式:sbb操作对象1,操作对象2
功能:操作对象1=操作对象1-操作对象CF
比如指令sbb ax,bx实现的功能是:(ax)=(ax)-(bx)-CF
11.8cmp标志
比较指令,cmp的功能相当于减法指令,是不保在结果cmp 指令执行后,较结果进行记录
将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果
cmp指令格式:cmp操作对象1,操作对象2
功能:计算操作对象1操作对象2但并不保存结果仅仅根据计算结果对标志寄存器进行设置。
11.9DF标志和串传送指令
方向标志位
在串处理指令中,控制每次操作后si,di的增减
df=0,每次操作后si,di递增
df=1,每次操作后si,di递减
11.11pushf和popf
直接访问标志寄存器的 方法:
pushf:将标志寄存器的值压栈
popf:从栈中弹出数据,送入标志寄存器中
第十二章内中断
中断:CPU不再接着(刚执行完的指令)向下执行,而是转去处理中断信息
内中断:由CPU内部发生的事件而引起的中断
外中断:由外部设备发生的事件而引起的中断
12.1内中断的产生,中断处理程序,中断向量表
cpu内部有下面的情况发生的时候,将产生相应的中断信息
1.除法错误
2.单步执行
3.执行into指令
4.执行int指令
CPU在收到中断信息后,转去执行该中断信息的处理程序
中断处理程序在哪里?中断信息和共处理程序的入口地址之间建立某种联系,使得CPU根据中断信息可以找到要执行的处理程序
中断向量表:CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址
12.2单步中断
程序的正常执行:取指令,改变CS:IP,执行指令,取指令
第十三章int指令
13.1int指令
int指令的格式为:int n,n为中断类型码
功能:引发中断过程
CPU执行int 指令,相当于引发一个n号中断的中断过程,执行过程如下。
(1)取中断类型码n;0三鲜天
(2)标志寄存器入栈,IF=0,TF-O;
(3) CS、IP入栈
(4) (IP)=(n*4),(CS)=(n*4+2)。
int指令的最终功能和call指令相似,都是调用一段程序
一般情况下,系统将一些具有一定功能的子程序,以中断处理程序的方式提供给应用程序调用
13.2BIOS和DOS
BIOS:
(1)硬件系统的检测和初始化程序:
(2)外部中断和内部中断的中断例程
(3)用于对硬件设备进行IO操作的中断例程:
(4)其他和硬件系统相关的中断例程。
第十四章端口
在PC机系统中,和CPU通过总线相连的芯片除各种存储器外,还有以下3种芯片。
(1)各种接口卡(比如,网卡、显卡上的接口芯片,它们控制接口卡进行工作:
(2)主板上的接口芯片,CPU通过它们对部分外设进行访问:
(3)其他芯片,用来存储相关的系统信息,或进行相关的输入输出处理。
在这些芯片中,都有一组可以由CPU 读写的睿存婴这些寄存器,它们在物理上可能处于不同的芯片中,但是它们在以下两点上相同。
(1)都和CPU的总线相连,当然这种连接是通过它们所在的芯片进行的:
(2)CPU对它们进行读或写的时候都通过控制线向它们所在的芯片发出端口读写命令。
CPU可以直接读写以下3个地方的数据。
(1)CPU内部的寄存器
(2)内存单元
(3)端口
第十五章外中断
15.1外中断
1.可屏蔽中断
CPU可以不分配的外中断
来自CPU外部
(1)取中断类型码n:
(2)标志寄存器入栈,IF-0,TF=0:
(3)CS、IP入栈;
(4) (P)=(n*4), (CS)-(n*4+2)
2.不可屏蔽中断
中断类型码固定为2
(1)标志奇仔器人栈>TF-0H-0:
(2)CDP人栈
(3)(P=(8),(CS)=(0AH)