首页
社区
课程
招聘
[旧帖] [原创]《汇编语言(第二版王爽)》读书笔记 0.00雪花
2012-8-1 23:45 3592

[旧帖] [原创]《汇编语言(第二版王爽)》读书笔记 0.00雪花

2012-8-1 23:45
3592
求分求码时期,就是每天都泡在看雪。
发点东西,希望对大家有用。
一周的时间读完王爽《汇编语言》(清华第二版),阅读之余,记下些笔记方便以后看。
排版可能有点乱,初次发帖,不足之处,敬请谅解。最后几张阅读略显仓促,所以就不放上来了。

++++++++++++++++++++++++++++++++++++++++++++++++

汇编语言-清华大学第二版 –读书笔记



第一章 基础知识

汇编语言有以下三种指令组成
1.	汇编指令:机器码的助记符,与机器码一一对应
2.	伪指令:无对应指令,由编译器执行,计算机并不执行
3.	其他符号 如+ - * /  编译器识别,无对应指令
指令和数据是应用上的概念
电子计算机最小的信息单元是bite 也就是一个二进制位 8bite=Byte Byte(即字节)为微型机存储器的存储单元。
微机存储器的容量是以字节为最小单元来计算的。
CPU要想进行数据的读写,必须和外部器件(芯片)交换一下三种信息
1.	存储单元的地址(地址信息)
2.	器件的选择,读或写的命令(控制信息)
3.	读或写的数据(数据信息)
总线从逻辑上分为3类:地址总线。控制总线,数据总线。
汇编指令 MOV AX [3]  含义 传送三号单元的内容入AX
一个CPU有N根地址总线,则可以说这个CPU的地址总线宽度为N,这样的CPU最多可以寻找2的N次方个内存单元 从0~(2的N次方-1)
数据总线的宽度决定CPU和外界的数据传送的速度。
8088CPU的数据总线宽度为8,8086CPU的数据总线宽度为16.
8088CPU 传送16位数据时,分两次传送,第一次先传送低位。
控制总线是个总称,控制总线使一些不同控制线的集合。他的宽度决定了CPU对外部器件的控制能力
汇编指令是机器指令的一种助记符,同机器指令一一对应、
每一种CPU都有自己的汇编指令集。
CPU可以直接使用的信息在存储器中存放,
在存储器中指令和数据没有任何区别,都是二进制信息。
存储单元从零开始顺序编号
一个存储单元可以存储8个bit  即8位二进制数
1Byte = 8bit 1KB= 1024 B   1MB= 1024KB  1GB= 1024MB
每一个CPU芯片都有许多管脚,这些管脚和总线相连也可以说这些管脚引出总线,一个CPU可以引出三中总线的宽度标志了这个CPU的不同方面的心能:
	地址总线的宽度决定了CPU的寻址能力;
	数据总线的宽度决定了CPU与其他器件进行数据传送时的一次数据传送量。
	控制总线的宽度决定了CPU对系统中其他器件的控制能力。
CPU对外部设备不能直接控制,直接控制这些设备进行工作的是插在扩展插槽上的接口卡。
存储器分类
	读写属性上:
随机存储器(RAM)和只读存储器(ROM)。随机存储器可读可写,必须带点存储,关机内容丢失。只读存储器只读不能写入,关机后内容不丢失。
	功能和连接上:
1.随机存储器 
存放绝大部分数据和程序。主存储器一般油两个位置上的RAM组成:主板上的RAM和插在扩展插槽上的RAM。	
		2.。装有BIOS的ROM
					BIOS ----Basic Input/ Output System基本出入/输出系统。BIOS 由主板和各类接口卡(如显卡 网卡)厂商提供的软件系统。在主板和某些接口卡上插有存储相应BIOS的ROM。
		3,接口卡上的RAM  最典型的是显卡上的RAM  即显存
CPU在操纵各种物理上相互独立存储器的时候,把他们当作内存看待,把他们总的看作一个由若干个存储单元组成的逻辑存储器。每一个物理存储器在这个逻辑存储器占一个地址段,即一段地址空间。
内存地址空间的大小受CPU的地址总线的宽度限制。8086CPU的地址总线宽度20,可以传送(0---2的20方-1)个地址信息,他的内存地址空间大小1MB   80386CPU地址总线32,则内存地址空间最大 4GB

第二章 寄存器

一个典型的CPU由运算器,控制器,寄存器等器件构成。这些器件靠内部总线相连。
不同CPU,寄存器的个数,结构是不同的。8086CPU有14个寄存器。分别是 AX  BX  CX  DX  SI  DI  SP  BP  IP  CS  SS  DS  ES  PSW, 均为16位寄存器。可以存放两个字节。  AX  BX  CX  DX 通常用来存放一般性数据。称为通用寄存器。这四个寄存器可分为独立使用的8位寄存器。
AX分为 AH AL  BX 分为 BH BL   CX 分为 CH CL  DX分为  DH  DL
AX的低8位构成AL  高8位构成 AH 寄存器。BX CX DX 同理。
字节: byte 由 8个bit构成。可以存放在8位寄存器中
字: word  有两个字节组成。分别成为这个字的 高位字节 低位字节。
十六进制后面加H  二进制后面加  B 
汇编指令和寄存器的名称不区分大小写。
如果 1044CH存入AX ,则最高位1不能保存,ax中数据位044CH
AL 作为独立8位寄存器使用时,与AH无关,进位不会保存到AH中
CPU为16位结构(16位机  字长为16等说法)
一.	运算器一次最多处理16位数据
二.	寄存器的最大宽度为16位
三.	寄存器和运算器之间的通路为16位。
8086CPU有20位地址总线,可传送20位地址,达1M的寻址能力。如果将地址从内部简单的发出,只能送出16位地址,寻址能力为64KB
8086CPU 用两个16位地址合成20位物理地址方法:1,CPU中相关部件提供两个16位地址,一个为段地址,一个为偏移地址。2:两个地址通过内部总线送入地址加法器。3:加法器将两个16位地址合成20位物理地址。
地址加法器: 物理地址=段地址*16+段移地址 
一个二进制数左移N位,相当于乘以2的N次方。
一个X进制数左移1位,相当于乘以X
基础地址+偏移地址=物理地址  其中:基础地址=段地址*16
段地址*16必然是16的整数倍,所以一个段的起始地址也一定是16的整数倍。偏移地址16位,16位地址的寻址能力为64KB 所以一个段的长度最大为64KB。
CPU可以用不同的段地址和偏移地址形成同一个物理地址。
“数据在21F60H内存单元中“对于8086PC 表达为:数据存在内存 2000:1F60单元中    数据存在内存的2000段中的1F60单元中。
段地址在8086PC的段寄存器中存放,8086CPU有四个段寄存器: CS DS  SS  ES 
CS为代码段寄存器,IP为指令指针寄存器。 设cs中为M  ip中为N ,则8086CPU将从M*16+N单元开始读取,即:CPU将CS:IP指向的内容当做指令。
读取一条指令后,IP中的值自动增加,以使CPU可以读取下一条指令。如果读入指令B82301长度为3个字节,IP中的字自动增加3.
8086CPU的工作过程:
一,	从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器。
二,	IP=IP+所读指令长度,从而指向下一条指令
三,	执行指令,转到一步骤,重复过程。
任何时候,CPU将CS:IP指向的内存单元中的内容看作指令。可以改变CS IP中的内容控制CPU执行目标指令
8086CPU大部分寄存器值都可用MOV(传送指令)指令改变,但其不能设置CS IP 中的值
能改变CS IP 的内容的指令通称为转移指令。 如JMP指令  jmp 2AE3:3 执行后 cs=2AE3H
Ip=0003H(因为寄存器为16位,故前面补充000)   jmp 段地址:偏移地址
仅修改IP中的内容:  jmp 某以合法寄存器  例如: jmp ax   用ax中的值修改IP

第三章 寄存器(内存访问)

内存是字节单元,一个字用两个地址连续的内存单元存放,字的地位字节放在低地址单元中。
8086CPU中有一个DS 寄存器,通常用来存放要访问的数据的地址段。
例:    MOV BX, 1000H
		MOV DS , BX
		MOV AL , [0] 以上三条指令将 1000:0中的数据读取到AL中
MOV指令可完成两种传送:一 将数据直接送入寄存器 二 将一个寄存器内容送入另一个
[0]表示一个内存单元,期货总0表示偏移地址,默认的段地址保存在DS段寄存器中
8086CPU不支持直接将数据传送入段寄存器这哦刚,所以 MOV DS 1000H 是非法的指令。只能用一个寄存器做中转,例如先送入bx 在mov ds bx
将AL 中数据送入内存单元1000H中:
		Mov bx ,1000H
		Mov ds , bx
		Mov [0] , al
只要在mov指令中给出的是16位的寄存器就可以进行16位数据的传送例如:mov ax, [0] 将传入[0][1]两部分进入ax  其中低位地址放在ax中的al 高位地址数据放入ax中的ah
Mov指令的几种形式:
Mov 寄存器,数据              mov ax,8
Mov 寄存器,寄存器            mov ax,bx
Mov 寄存器,内存单元          mov ax ,[0]
Mov 内存单元,寄存器          mov [0],ax
Mov 段寄存器,寄存器          mov ds,ax
Mov 寄存器,段寄存器          mov sx,ds
Mov 内存单元,段寄存器
Mov 段寄存器,内存单元
Add 指令的几种形式 	
Add 寄存器,数据 add 寄存器,寄存器  add 寄存器 ,内存单元 add 内存单元,寄存器
Sub 指令的几种形式
Sub 寄存器。数据  sub 寄存器,寄存器 sub 寄存器,内存单元 sub 内存单元,寄存器
栈的两个基本操作;入栈和出栈。遵循后进先出,LIFO (last in first out)
Push ax 表示将寄存器ax中的数据送入栈中,pop ax 表示从栈顶取出数据送入ax  
8086CPU的入栈出栈操作都是以字为单位进行高地址放入寄存器高八位。高低相互对应。
8086CPU中有两个寄存器 段寄存器SS和寄存器 SP   栈顶的段地址存放在SS中,偏移地址存放在SP中。任意时刻,SS:SP指向栈顶元素。
每次push ax 的执行,有两部分组成  (1)SP=SP-2 ,SS:SP指向当前栈顶的前面的单元,以当前栈顶前面的单元为新的栈顶,(2)将ax中的内容送入SS:SP指向的内存单元处。SS:SP此时指向新的栈顶。
入栈时,栈顶从高地址向低地址增长
栈空,SS:SP指向栈空间最高地址单元的下一个单元。该单元的偏移地址为栈最底部的字单元的偏移地址+2。如1000H—1000FH当作栈,为空栈,则此时SS=1000H  SP=0010H
每次执行 pop ax分两部分:1。将SS:SP指向的内存但愿数据送入ax    2 。SP=SP+2  SS:SP指向栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
出栈后,SS;SP 指向心的栈顶,POP操作前的栈顶元素仍存在于原内存地址,数据不变,当再次执行push等入栈命令后,此数据将被覆盖重写。
栈满push和栈空pop会出现栈顶超界的问题。
Push指令的几种格式 pop同
Push 寄存器 push 段寄存器  push 内存单元  可只给出内存单元偏移地址,段地址在DS
栈的段地址不能直接送入数据,需要一中介寄存器中转。
将ax 中数据清零: move ax,0   或者 sub ax,ax
用栈暂存以后要恢复的数据时,出栈的顺序和入栈的顺序相反。错误的使用可用来交换数据
Push pop操作只修改SP  栈顶的变化范围最大为 0~FFFFH
栈段长度N=《64KB起始地址为16的整数倍的内存单元。如 10000H~1FFFFH的栈空间为64KB ,此时 SS=1000H  SP=0000H
对于数据段,段地址在DS中,对于代码段,段地址在CS中,偏移地址在IP中,对于栈段,段地址在SS中,栈顶单元的偏移地址在SP中。关键在于CPU中寄存器的设置。

第四章 第一个程序

简单程序例 	
			Assume  cs:codesg   含义为假设将段与相关的寄存器关联起来
			codesg  segment          segment 和ends功能定义一个段,segment段开始,
					mov ax,0123H        ends段结束  格式为  段名 segment  
					mov bs,0456H                            段名 ends
					add ax,bx
					add ax,ax
					mov ax,4C00H         assume  segment ends   end为三个伪指令
					int 21H
			codesg  ends 		
			end                      结束标记
codesg称为标号,一个标号代表一个地址,最终编译成一个段地址。
一个程序结束后,将CPU的控制权交还给使它得以运行的程序,这个过程为:程序的返回
Mov ax,4C00H        ----------
Int 21H                ----------这两指令实现程序的返回(原理后面)
运行---cmd—edit   DOS下的edit,其中alt+enter为全屏模式
编译用masm 5.0   连接用 overlay linker3.60
DOS模式—进入masm目录,运行mams.exe  如果源程序文件在当前文件下,则输入文件名(扩展名为asm时)或者文件名.扩展名  例如输入  pi或者 pi.txt
编译时,最多得到三个输出:目标文件(.obj) 列表文件(.list)交叉引用文件(.crf)后两者中间结果可以忽略他的生成
运行目录下link.exe ,中间出现 输入镜像文件(.map)和所需的库文件(.lib) 按情况忽略。
简化方式编译链接:masm c:\1;注意有分号    link 1;注意有分号
任何操作系统都提供一个shell (外壳)程序,如DOS中的command.exe即命令解释器
一个汇编程序从写出到执行的全部过程:编程(edit)---1.asm----编译(masm)---连接(link)---1.exe---加载(command.exe)----内存中的程序----设置CPU中的CS:IP(command.exe)----运行(cpu)---结束回到command.exe
观察程序运行过程可用debug,debug可以把程序加载入内存,设置CP:IP,但不会放弃CPU控制权。   如 命令行输入 debug  1.exe
R命令查看各个寄存器设置状态,CX中存放程序长度。
DOS系统中EXE的加载过程
一,	找到一段起始地址为SA:0000(即起始地址的偏移地址为0)的容量足够的内存空间,
二,	在这段内存前256个字节中,创造一个称为程序前缀(PSP)的数据区,DOS要利用psp和被加载的程序进行通信
三,	从这段内存区的256字节处开始(在PSP的后面)将程序装入,程序的地址被设为SA+10H:0 ;(内存空间去从SA:0开始0—255字节为PSP,从256字节处开始放程序,为了更好的区分PSP和程序,DOS一般将他们划分到不同的段中,
内存空间区:  SA:0
PSP区:  SA:0
程序区: SA+10H:0     注意PSP区虽然和程序区物理地址连接,却有着不通的段地址、
四,	将该内存的段地址放入DS中,初始化其他相关寄存器,设置CS:IP指向程序入口
DS=SA   CS:IP=SA+10H:0=DS+10H:0
程序加载后,DS中存放着程序所在内存区的段地址,偏移地址为0,故程序所在内存区DS:0
DS中尅得到PSP的段地址SA,PSP的偏移地址为0,物理地址为SA*16
Debug中-U指令查看程序指令,T命令单步执行程序的每一条指令、到int 21h时用P命令

第五章 [BX]和loop指令

[BX]表示一个内存单元,偏移地址在BX中。如 mov ax,[bx]  将一个内存单元送入ax,单元长度2字节,偏移地址在bx,段地址在ds中。如果 mov al,[bx] 则单元长度为一字节
“()”表示一个寄存器或者一个内存单元中的内容  例 (ax)表示ax中的内容(20000H)表示内存20000H中的内容 注意括号中地址为物理地址
“()”中可有三种类型:寄存器名  段寄存器名  内存单元物理地址(一个20位数据)
对于mov ax,[2],可以描述为 (ax)=((ds)*16+2 )
 push ax 描述(SP)=(SP)-2   ((SS)*16+(SP))=(AX)
POP AX 的描述  (AX)=((SS)*16+(SP))  (SP)=(SP)+2
(X)数据类型根据X决定  (al)为字节型  (ax)为字型 .(al)=(20000H) 则(20000H)得到的数据类型为字节型  (ax)=(20000H)则(20000H)得到的数据类型为字型
约定符号idata表示常量,mov ax, [idata] 代表mov ax,[1]等 mov ax, idate 代表mov ax,1等
Inc bx 的含义是bx中的内容加1
Loop指令格式:loop,标号。CPU执行LOOP指令的时候,第一:(CX)=(CX)-1第二;判断CX中的值,不为零转到标号处继续执行,为零则向下执行
程序例: assume cs:code                           程序框架    
		 code segment                                       mov cx,循环次数
			mov ax,2                                  s:(标号)
			mov cx,11  cx中存放循环次数	                   循环执行的程序段
		s: add ax,ax      标号s代表一个地址,             loop s  
			loop  s
			mov ax,4C00H
			int  21h
		code ends
		end
在汇编源程序中,数据不能以字母开头。所以ffffh 要写成0ffffh
Debug加载程序后,程序在DS+10H 处,
Debug 的g命令,可以跳过程序段。例如  g  0012  表示程序执行到当前代码段(段地址在CS中)的0012H处。Debug将从当前的CS:IP执行,一直到(IP)=0012H为止。
当希望将循环一次执行完用p命令。当再次遇到loop指令时,用P,会自动重复执行循环 
直到(cx)=0为止
Debug和masm汇编编译器对于指令处理有所不同。如mov ax,[0] debug 送入内存单元[0]内数据入 ax。Masm编译器则送入 [0],他会把指令[idata] 解释为idata
所以:一:如果访问内存[]用的常量idata 则要在[idata]前显式给出段寄存器  Mov ax,ds:[0]
	  二:如果在[]里用寄存器,如BX,则默认段地址在ds中,则可不显式给出段寄存器
	如:mov ax, 2000h     Mov ds,,ax     Mov bx,0    Mov al,[bx]
若ffff:0006(字节型8位)单元向ax(16位字型)赋值,应该令(ah)=0,(al)=(ffff5H)
在做加法的时候,注意两个问题:类型的匹配和结果的不超界。如(dx)=(dx)+内存中8位数据  存在类型不匹配。  (dl)=(dl)+内存中8位数据 存在结果超界的可能性。
解决方法:  用到16位寄存器做中介     	mov al,ds:[0]
									  	Mov ah,0
										Add dx,ax----赋予al ah后可直接用ax
循环结构中内存地址递增的方法:循环前 令DX=偏移地址量 如dx=0  循环中mov ax,[bx]  。。。。其他代码。。。inc bx (使ds:bx指向下一单元)
访问内存时。 Mov ax,ds:[bx]   mov ax,cs:[bx] 其中 ds  cs等用显式的指明内存单元段地址的称为 段前缀
DOS方式下,一般情况。0:200~~0:2ff空间中没有系统或其他程序数据或代码
0:200~~0:20B 单元等同于 0020:0~~0020:b 单元。描述同一段内存空间

第六章 包含多个段的程序
Dw  0123H,0456H  dw定义字型数据 dw即“define word”,多个数据中间用逗号隔开
,
程序例: 	assume cs:code              	CPU如何设置CS:IP---由可执行文件中的
			Code segment	               	描述信息指明、程序=描述信息+程序。描述
			   Dw,0122H,0456H,0566H    	信息由编译连接时候得到的信息。
			Start:      	mov bx,0			程序框架:	assume cs:code
						mov ax,0						code segment
						mov cx,3							…..相关数据….
				s:		add ax,cs:[bx]					start:
						add bx,2							….相关代码….
						loop s						code ends
					mov ax,4c00h						end start
					int 21h
			code ends
			end start   end 除了通知编译器程序结束处,还通知入口
在代码段中使用栈: 程序例
	Assume cs:codesg
	Codesg segment
			Dw  0123h,0456h,0789h, 0123h,0456h,0789h, 0123h,0456h  用dw定义16个字
			Dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0    型数据,在加载后,获得16个字空间
	Start::	mov ax,cs						把此空间当作栈使用
			Mov ss,ax
			Mov sp,30H    将设置栈顶SS:SP指向 CS:30
			Mov bx,0
			Mov cx,8
		S: 	push  cs:[bx]
			Add bx,2
			Loop s
			Mov bx,0
			Mov cx,8
		S0:	pop cs:[bx]
			Add bx,2
			Loop s0
			Mov ax,4c00h
			Int 21h
	Codesg ends
	End start                  指明程序入口在start处
将数据,代码栈放入不同的段 程序例:
	 Assume cs:code,ds:data,ss;stack
	Data segment
			Dw  0123h,0456h,0789h, 0123h,0456h,0789h, 0123h,0456h
	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     段名就相当于一个段地址,例如stack  data  stack:6 注意
			mov ss,ax        段明用作段地址时不能直接赋值给段寄存器,
			mov sp,20H		CPU区分代码,数据,栈并不是根据段名code stack等,也
			mov ax,data      不是根据Assume cs:code,ds:data,ss;stack(assume为伪指令)
			mov ds,ax		而是根据 end start确定程序入口并写进执行文件的描述信
			mov bx,0			息中  再根据汇编指令中对CS:IP SS:SP DS等寄存器的设
			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指令按位进行与运算,可用来设置相应位为0.如and al 10111111B 第六位设0
Or按位或运算。可用来设置相应位为1.如 or al 01000000B  第六位设为1
用‘’成对单引号方式指明的数据为字符形式,编译器会转为ASCII码  如db ‘usex’	
小写字母的ASCII码值比大写的ASCII码大20H 
如果(al)>61H,则为小写字母的ASCII码。。61界限  转换为大写 sub al,20H
一个字母,不管原来是大小写,将他的第五(从0开始数,即右数第六位)位置0则变成大写,置为1则变成小写字母。如A 01000001B   a 01100001B
相关代码:  mov al,[bx]  将ASCII码从ds:bx指向单元中取出
			And al,11011111B  将al中的ASCII码的第五位置0,变成大写
		   ( or al 00100000B   将al中ASCII码的第五位置为1,变成小写)
			Mov [bx],al  将转变后的ASCII码写回原单元
			Inc bx    (bx)加1,ds:bx 指向下一字母
Mov ax,[bx+idata] 偏移地址为bx的数值加上idata 例如idata=200,则(ax)=((ds)*16+(bx)+200)  也可写成 mov ax,[200+bx]  mov ax,200[bx]  mov ax,[bx].200
SI和DI是8085CPU中和BX 功能相似的寄存器,不能够分为两个8位寄存器使用。
几种不通的寻址方式:
	① [idata]用一个常量表示地址,可用于直接定位一个内存单元
	② [bx]用一个常量来表示内存地址,可用于简介定位一个内存单元
	③ [bx+idata]用一个常量和变量表示地址,可以在一个起始地址的基础上用变量间接定位一个内存单元
	④[bx+si]用两个变量表示地址
	⑤[bx+si+idata]用两个变量和一个常量表示地址、
镶嵌式两级loop循环,两个循环共用一个cx,相互之间会造成影响,应该在进入内一级循环时保存外级CX于一寄存器中。
例:错误程序:                                  正确程序
	Mov cx,4									Mov cx,4			
S0:	mov si,0                              s0:	mov dx,cx
	Mov cx,3									mov si,0
S: 	mov al,[bx+si]								mov cx,3
	And al,11011111B						s:  mov al,[bx+si]
	Mov [bx+si],al							And al,11011111B	
	Inc si									Mov [bx+si],al	
	Loop s									Inc si
	Add bx,16								Loop s	
	Loop s0									add bx,16
											Mov cx,dx
											Loop s0
数据的暂存(如上)可以选用寄存器,但上述方法不是一般化的方法。可以就需要开辟一段内存空间,暂存各种数据。
一般来说,在需要暂存数据的时候,我们能都应该使用栈。

第八章 数据处理的两个基本问题

引入描述性符号 reg表示一个寄存器,sreg表示一个段寄存器。Rg集合包括 AX BX CX DX AH AL BH BL CH CL DH DL SP BP SI DI     sreg的集合包括ds ss cs es
在8086CPU中只有四个寄存器可以用在[…]中  分别为 BX SI DI BP。在[….]中四个寄存器可单独出现,或只能以四种组合出现:BX和SI  Bx和di bp和si   bp和di
只要在[….]中使用bp,并且没有显性给出段地址,则段地址默认在SS中
指令在执行前,所要处理的数据可以在三个地方:CPU内部,内存,端口
汇编语言用三个概念表达数据位置①立即数(idata)②寄存器③段地址SA和偏移地址EA
Bx和si di的组合段地址默认在ds中,bp和si di的组合段地址在ss中
8086CPU的指令可以处理byte 和word两种尺寸数据。字操作。字节操作。
确定字操作还是字节操作:①根据指令中的寄存器②用操作符X  ptr指明内存单元长度,X可以是word 或者byte  例: mov word ptr ds:[0],1   mov byte ptr ds:[0],1  ③有些指令默认访问的是字单元还是字节单元,例如push pop 
[bx+idata] 其他表示方法  [bx].idata用于结构体  idata[bx]用于数组  [bx][idata]用于二维数组     [bx+si]其他表示方法	[bx][si]用于二维数组   [bx+si+idata]其他表示方法[bx].idata[si]用于表格(结构)中的数组项   idata[bx][si]用于二维数组。 
div除法指令① 除数有8位和16位两种②被除数:默认放在AX或者DX和AX中,如果除数为8位,则被除数16位,默认放在AX中,如果除数为16位,则被除数为32位,在DX和AX中存放,DX存放高16位,AX存放低16位。③如果除数为8位,则AL中存放除法操作的商,AH存储除法操作的余数。如果除数为16位,则AX中存放除法操作的商,DX中存放操作的余数。  
Div byte ptr ds:[0] 含义 (al)=(ax)/((ds)*16+0)的商 (ah)=(ax)/((ds)*16+0)的余数
Div word ptr es:[0] 含义	(ax)=[(dx)*10000H+(ax)]/((es)*16+0)的商
						(dx)=[(dx)*10000H+(ax)]/((es)*16+0)的余数
计算100001/100  分析:被除数大于65535,不能用ax寄存器存放,只能那个用dx和ax两个寄存器联合存放,除数100小于255.可用一个8位寄存器存放,但是被除数是32位,除数应该为16位(16位---8位。。32位---16位应该相互对应),所以要用一个16位寄存器存放除数100  100001十六进制 186A1H 
mov dx,1
Mov ax,86A1H   (dx)*10000H+(ax)=100001
Mov bx,100
Div bx
dd是用来定义dword (double word双字)型数据的。占两个字内存空间。
dup是一个操作符,在汇编语言中同db dw dd,有编译器识别处理的符号。与db dw dd 数据定义伪指令配合使用,用来进行数据的重复。
db 3 dup(0) 定义了3个字节,值都是0.相当于db0,0,0
db 3 dup(0,1,2)9个字节,分别是0,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’
dup使用格式      db/dw/dd 重复次数  dup(重复的相应类型数据)

第九章 转移指令的原理

可以修改IP或者同事修改IP 和CS的指令统称为转移指令,即可以控制CPU执行内存某处代码的指令。只修改IP的称为段内转移 jmp ax 同时修改IP CS的为段间转移 jmp 1000:0
对IP修改范围不同:短转移(-128~~127),近转移(-32768~~32767)
又分为:无条件转移指令(jmp) 。 条件转移指令。  循环指令(loop) 。过程 。 中断
offset 取得标号的偏移地址,编译器处理。 	assume cs:codesg
										codesg segment
	相当于mov ax,0							start: mov ax,offset start 此指令占3字节
	相当于mov ax,3							s:	mov ax,offset s
										codesg ends
										end start
------------------------------------------根据位移进行转移的jmp指令----------------------------------
jmp shrot 标号(转到标号处执行指令),实现段内短转移。最多向前128字节,向后127字节(-128~~127)shor 表明短转移。
汇编指令中的idata(立即数)不论表示一个数还是表示内存单元。都会在相应的机器码中出现。  如mov ax,0123h  机器指令B8 23 01 mov ax,ds:[0123h] ----A1 23 01
CPU在执行jmp指令的时候并不需要目的地址。
jmp short 标号  的功能为:(IP)=(IP)+8
①	8位位移=标号处的地址-jmp指令后的第一个字节地址
②	short指令表明此处的位移为8位位移
③	8位位移的范围为-128---127,用补码表示。
④	8位位移有编译程序在编译时算出
jmp near ptr 标号    实现的段内近转移
①	16位位移=标号处的地址-jmp指令后的第一个字节的地址
②	near ptr 指明此处的位移为16位位移,进行的是段内近转移
③	16位位移的范围为 -32768~~32757 补码表示
④	16位位移由编译程序在编译的时候算出。
--------------------------------------------转移的目的地址在指令中的jmp指令--------------------------
jmp far ptr 标号  实现的是段间转移,又称为远转移(CS)=标号所在段的段地址(IP)=标号在段中的偏移地址。
如jmp far ptr 标号所对应的相应机器码 EA 0B 01 BD 0B 则0B 01 BD 0B是目的地址在指令中的存储顺序,高地址的BD 0B是转移的段地址0BBDH,低地址0B 01是偏移地址010BH
--------------------------------------------转移地址在寄存器中的jmp指令--------------------------------
jmp 某一合法寄存器(16位。 ax等)   指令的功能为:用寄存器中的值修改IP
---------------------------------------------转移地址在内存中的jmp命令-----------------------------------
①	jmp word ptr 内存单元地址(段内转移)功能内存单元地址处存放的一个字的内容是转移的目的偏移地址。mov ax,0123H  mov ds:[0],ax  jmp word ptr ds:[0]执行后IP=0123H
②	jmp dword ptr 内存单元地址(段间转移) 功能:内存单元开始处存放的两个字,高地址出存放的目的的段地址,低地址处转移的目的偏移地址。 
mov ax,0123H   mov ds:[0],ax   mov word ptr ds:[2],0  jmp dword ptr ds:[0]执行后CS:IP指向0000:0123
jcxz指令为有条件转移指令,所有的有条件转移指令都是短转移。机器码中只包含转移的位移。范围-128~~127,“jcxz  标号”当cx=0时,执行jmp short 标号,cx=0时什么也不做。
所有的循环指令都是短转移。机器码中只包含转移的位移。

第十章 CALL和RET指令

RET指令使用栈中的数据,修改IP中的内容,实现近转移.RETF指令用栈中的数据,修改CS和IP中的内容,实现远转移。
CPU执行ret命令时候① (IP)=((SS)*16+(SP))   (SP)=(SP)+2相当于 POP IP
CPU执行retf指令时候①(IP)=((SS)*16+(SP))  ②(SP)=(SP)+2 ③(CS)=((SS)*16+(SP))④(SP)=(SP)+2 相当于(POP IP   POP CS)-----实际不能这么写。
call指令不能实现短转移。
---------------------------------根据位移进行转移的CALL指令-------------------------------
格式:  “call 标号”(将当前的IP压栈后,转移到标号处执行指令)
①(SP)=(SP)-2  ((ss)*16+(sp))=(ip) ② (IP)=(IP)+16位位移 相当于pop ip
 jmp near ptr 标号
---------------------------------转移的目的地址在指令中的CALL指令----------------------------
call far ptr 标号 实现段间转移。CPU执行步骤:①(SP)=(SP)-2  ((ss)*16+(sp))=(cs)   (SP)=(SP)-2  ((ss)*16+(sp))=(ip)②(cs)=标号所在段内的段地址
(ip) =标号所在段中的偏移地址。相当于:push cs  push ip    jmp far ptr 标号
----------------------------------转移地址在寄存器中的CALL指令------------------------------
格式:“call 16位reg(如ax)”功能:(sp)=(sp)-2  ((ss)*16+(sp))=(ip)  (ip)=(16位寄存器)
相当于  push ip    jmp 16位寄存器
---------------------------------转移地址在内存中的CALL指令--------------------------------------
一:call word ptr 内存单元地址 相当于  push ip   jmp word ptr 内存单元地址
二:call dword ptr 内存单元地址 相当于push cs    push ip  jmp dword  ptr 内存单元地址 
具有子程序的源程序的框架如下:
	assume cs:code	
	code segment
		main:……..
			call  sub1       子程序调用su1
			………..
			mov ax 4c00h
			int 21h
		sub1:…….	        子程序sub1开始
			call sub2			调用子程序sub2
			………
			ret				子程序返回
		sub2:……			子程序sub2开始
			ret				子程序返回
		code ends
		end main
mul乘法指令:①两个相乘的数要么都是8位,要么都是16位。如果都是八位,一个默认放在AL中,另一个放在8位寄存器中或者内存字节单元中。如果都是16位,一个默认在AX中,另一个放在16位寄存器中或者内存字单元中。②如果8位相乘,结果默认在AX中,如果16位,结果高位默认DX,低位默认AX。
格式: mul  reg         mol 内存单元 :例mul byte ptr ds:[0]   mul word ptr [bx+si+8]
内存单元可以用不同的寻址方式给出。
例100*10  mov al,100  mov bl,10  mul bl  100*10000  mov ax,100 mov bx,10000  mul bx
CALL 和RET指令实现了汇编语言程序中的模块化设计。
单个参数的传递可以用寄存器和内存。多个参数的传递可以用内存。然后将内存空间首地址放入寄存器中,传递给子程序。
子程序中使用的寄存器可能主程序中也在使用,从而造成冲突。解决方法在子程序开始将及程序中所有用到的内容都保存起来,在在子程序结束前恢复。用栈来保存。
编写子程序的标准框架:	子程序开始:子程序中使用的寄存器入栈
									子程序内容		
									子程序中使用的寄存器出栈
									返回(ret  retf)		

第十一章  标志寄存器	

标志寄存器简称flag(不通处理机个数和结构可能不同)①用来存储相关指令的某些执行结果②用来为CPU执行相关指令提供行为依据③用来控制CPU的相关工作方式。
8086CPU	表示寄存器有16位,存储的信息称为程序状态字(PSW)
0位CF  2位PF  4位AF  6位ZF  7位SF  8位TF  9位IF  10位 DF  11位OF
6位ZF 零标志位,如果相关指令执行结果为0,则zf=1,结果不为0则zf=0。
8086CPU大多是运算指令(逻辑或者算数)的执行结果会影响标志寄存器。如 add sub mul div inc or and
2位PF 奇偶标志位。检验指令执行后结果中所有bit位中1的个数是否为偶数,如果为偶数,则PF=1,如果为奇数,PF=0. 如: mov al,1  add al,10  结果00001011B,PF=0
7位SF  符号标志位,记录相关指令执行后结果是否为负。如果为负则SF=1.
对于同一个二进制数据,计算机可以将他当作无符号数来运算,也可以当作符号数据运算,其结果数据形式一样,根据有无符号代表不同数据。
0位CF进位标志位。在进行无符号数运算的时候,它记录了结果的最高有效位向更高位的进位值或者从更高位的借位值。(进位或者借位)
mov al,98H
add al,al	执行后(al)=30H,CF=1,cf记录了最高有效位向更高位的进位值
add al,al	执行后(al)=60H。CF=0,cf记录了最高有效位向更高位的进位值

mov al,97H
sub al,98H	执行后(al)=FFH CF=1 cf记录了向更高位的借位值。
sub al,al	执行后(al)=0 cf=0  cf记录了向更高位的借位值。
对于8位的有符号数据,机器所能表示的范围就是128~~127,同理,对于16位的有符号数据,机器所能表示的范围是-32768—32767如果超出范围则产生溢出。
11位的OF 溢出标志位。如果溢出,则OF=1
例:mov al,98  add al,99  add执行后CF=0,OF=1.cpu在执行add等指令的时候包含两种含义:无符号运算和有符号运算。CF记录无符号运算是否产生了进位。OF记录有符号数运算是否产生了溢出。对于无符号,99+98无进位,对于有符号预算,99+98溢出。
adc是带进位加法指令。他利用了CF位上记录的进位值。
指令格式:adc 操作对象1,操作对象2
功能:操作对象1=操作对象1+操作对象2+CF
比如指令adc ax,bx 实现的功能是  (ax)=(ax)+(bx)+CF
例:mov ax,2 mov bx,1  sub bx,ax  adc ax,1   执行后(ax)+1+CF=2+1+1=4
例:mov al,98H  add al,al  adc al,3  执行后:(al)+3+CF=34H
根据adc前面的指令确定cf含义,如果是sub则是借位,如果是add则是进位。
add ax,bx  与下面指令具有相同效果: add al,bl   adc ah,bh
计算1EF000H+201000H  结果放在ax (高16位)和bx(低16位)中
mov ax,001EH  mov bx,0F000H  add bx,1000H adc ax,0020H
sbb是带借位的减法指令,他利用了CF位上记录 的借位值。
指令格式:sbb 操作对象1,操作对象2
功能:操作对象1=操作对象1-操作对象2-CF
比如指令 sbb ax,bx 实现的功能是:(ax)=(ax)-(bx)-CF
计算003E1000H-00202000H  结果放在ax,bx 中 
	mov bx,1000H  mov ax,003EH   sub bx,2000H  sbb,ax,0020H
cmp是比较指令,功能相当于减法指令,只是不保存结果
cmp指令格式: cmp 操作对象1,操作对象2
功能:计算操作对象1-操作对象2 但不保存结果,仅仅根据结果对标志寄存器进行设置。
例如cmp ax,ax 做(ax)-(ax)运算,结果为0,但不在ax中保存,影响flag相关各位。执行后zf=1  pf=1  sf=0  cf=0 of=0。可根据ZF值判断两个数据是否相等。
CPU在执行cmp指令的时候也包含两种含义:进行无符号数运算和进行有符号数运算。
不能根据SF=1就断定 操作对象1<操作对象2. (ah)=22H (bh)=0A0H 则(ah)-(bh)=34-(-96)=82H   82H是-126的补码。
所得到的相应结果的正负并不能说明运算应得到的结果的正负。正是在运算中可能发生溢出。如果有这种情况发生,那么,sf的值就不能说明任何问题。
cmp ah,bh ①.sf=1,of=0   of=0说明没有溢出,则逻辑上的真正结果的正负=实际结果的正负。sf=1  则实际结果为负,所以逻辑上的真正结果为负  (ah)<(bh)②sf=1  of=1
of=1,说明有溢出,逻辑上的真正结果的正负不等于实际结果的正负。sf=1 实际结果为负。
如果因为溢出导致了实际结果为负,那么逻辑上真正的结果必然为正。(ah)>(bh)
③sf=0 of=1   of=1说明有溢出,逻辑上真正的结果的正负不等不实际结果的正负。sf=0实际结果非负。如果因为溢出导致了实际结果为正。那么逻辑上真正的结果必然为负。(ah)<(bh)④sf=0  of=0   of=0说明没有溢出,实际的正负=逻辑上真正的正负。(ah)》=(bh)
所有条件转移指令的转移位移都是[-128,127] 如jcxz 检测cx是否为0
大多数条件转移指令都检测标志寄存器的相关标志位,根据检测结果决定是否修改IP。
下面是常用的根据无符号数的比较结果进行转移的条件转移指令
指令				含义					检验的相关标志位
je 					等于则转移				zf=1
jne 					不等于则转移			zf=0
jb					低于则转移				cf=1
jnb					不低于则转移			cf=0
ja					高则转移				cf=0且zf=0
jna					不高则转移				cf=1,或者zf=1
例:如果(ah)=(bh)则(ah)=(ah)+(ah),否则(ah)=(ah)+(bh)
cmp ah,bh										|	例2  	mov ax,0
je s			如果(ah)=(bh) cmp ah,bh使zf=1	|			add ax,0	zf=1
add ah,bh										|			je s	转移
jmp short ok										|			inc ax
s:add ah,ah										|			s:inc ax  
ok:: 											|				执行后ax=1
可直接考虑cmp和je等指令配合使用是表现的逻辑含义,类似高级语言中的IF
flag的第10位是DF 方向标志位 在串处理指令中,控制每次操作后DI SI 的增减
DF=0 每次操作后si di 递增  DF=1 每次操作后si di 递减
串传达指令  格式 movsb  功能 执行movsb相当于① ((es)*16+(di))=((ds)*16+(si))② 如果df=0 则(si)=(si)+1 (di)=(di)+1 如果df=1 则(si)=(si)-1 (di)=(di)-1    
dec si  =(si)=(si)-1  递减指令
movsb的功能是将ds:si单元内存中的字节送入es:di,然后根据DF值si di递增或者递减
格式 movsw  和movsb类似,传送的为一个字的大小而非movsb的一个字节大小
一般来说,movsb和movsw都和rep配合使用。格式   rep movsb   用汇编语法描述其功能就是  s: movsb      loop s   rep根据cx的值重复执行后面的串传送指令。
rep 每次执行si di相应增减,故rep movsb 可以循环实现(cx)个字符的传送。
cld 指令将标志寄存器的DF位置0
std 指令将寄存器的df位置1.
例:用串传送指令将data段第一个字符串复制到后面的空间中
data segment					要使用串传送必要的信息:①传送的原始位置ds:si②传送
	db ‘welcome to masm’		的目的位置 es:di ③传送的长度 cx④ 传送的方向 df
	db 16 dup(0)
data ends
mov ax,data 
mov ds,ax
mov si,0					ds:si指向data:0
mov	 es,ax
mov di,16				es:di指向data;0010
mov cx,16				cx设置为16,rep循环16次
cld						df=0。正向传送、
rep movsb
pushf的功能是将标志寄存器的值压栈,popf的功能是从栈中弹出数据,送入标志寄存器。
在debug中,标志寄存器是按照有意义的各个标志位单独表示的。在debug中。OF—NV
DF—UP    SF—PL  ZF—NZ  PF—PO  CF—NC 

第十二章 段内中断

中段信息 CPU不在接着刚执行完的命令向下执行,而是转去处理这个特殊的信息。
中断信息可以来自CPU内部和外部。
产生内部中断情况:①除法错误,如执行div指令产生的除法溢出②单步执行③执行into指令④执行int 指令。
8086CPU用称为中断类型码的数据来标识中断信息的来源。
中断类型码为一个字节型数据,可表示256种中断信息来源。
以上四种中断源在8086中的中断类型码:① 0 ② 1 ③4 ④指令格式int n,n为中断类型码(立即数类型)
跟怒CPU的设计,中断类型码的作用就是用来定位中断处理程序。
CPU用8位的中断类型码通过中断向量表找到相应的中断处理程序的入口地址。
中断向量表在内存中保存,其中存放着256个中断源所对应的中断处理程序入口地址。
8086CPU机,中断向量表制定存放在内存地址0处,0000:0000到0000:03ff这1024个单元存放着中断向量表。一个表项占两个字,高地址字存放段地址,低地址字存放偏移地址。
由中段类型码—中断向量表中中断处理程序入口—设置cs ip –cpu运行中断处理程序。整个工作由CPU硬件自动完成,整个过程称之为 中断过程。
完整的中断过程:①(从中断信息)取得中断类型码②标志寄存器的值入栈(因为中断过程中要给边标志寄存器的值)③设置标志寄存器的第8位TF和第9位IF的值为0 ④CS中的内容入栈⑤ IP中的内容入栈 ⑥ 从内存地址为中段类型码*4和中断类型码*4+2的两个字单元中读取中断处理程序的入口地址设置IP和CS。
中断处理程序必须一直存储在内存某段空间之中。
iret指令的功能用汇编语言描述为: pop ip   pop cs    popf。该指令执行完后。CPU回到执行中断处理前的执行点继续执行程序。 
计算代码长度  :mov cx offset do0end-offset do0
				do0: 	。。。。。
						mov ax,4c00H
						int 21h
				do0end;	nop
CPU在执行完一条指令后,如果检测到标志寄存器的TF位为1,则产生单步中断,引发中断过程,中断类型码为1.
有些情况CPU在执行完当前指令后即使发生中断,也不会相应。例如在设置ss sp指令执行玩设置ss后,产生中断。CPU暂不响应中断,而是让ss 和sp指令连续设置完后在相应。
如果ss完后就中断,要在栈中压入标志寄存器 CS 和IP的值,但ss改变,SP未改变,故ss:sp指向的是不正确的栈顶。从而引发错误。

第十三章  int指令

int指令的格式为:int n ,其中n为中断类型码,他的功能是引发中断过程。
CPU执行int n指令,相当于引发一个n号中断的中断过程,执行过程如下:
①	取中断类型码n
②	标志寄存器入栈,IF=0  TF=0
③	CS  IP入栈
④	(IP)=(n*4)  (CS)=(n*4+2)
可以在程序中使用int指令调用任何一个中断的中断处理程序。
一般情况下,系统将一些具有一定功能的子程序,以中断处理程序的方式提供给应用程序调用。可以用int指令调用这些子程序。也可自己编写 中断例程。
例:编写 安装中断7CH的中断例程:
功能:将一个全是字母,以0结尾的字符串,转会为大写
参数:ds:si指向字符串的首地址
应用举例:将data段中的字符串转化为大写
assume cs:code
data segment
	db’conversation’,0
data ends
code segment
	start: 	mov ax,date
			mov ds,ax
			mov si,0
			int 7ch
		mov ax,4c00h
		int 21h
	code ends
	end start
安装程序如下
	assume cs:code
	code segment
		start:		mov ax,cs
				mov ds,ax
				mov si,offset captial
				mov ax,0
				mov di,200h
				mov cx,offset capitalend-offset capital
				cld		
				rep movsb
				mov ax,0
				mov es,ax
				mov word ptr es:[7ch*4],200h
				mov word ptr es:[7ch*4+2],0
				mov ax,4c00h
				int 21h
		capital:	push cx
				push si
		change;	mov cl,[si]
				mov ch,0
				jcxz ok
				and byte ptr [si],11011111B
				inc si
				jmp short change
		ok:		pop si
				pop cx
				iret
		capitalend:	nop
	code ends
	end start
BIOS主要包含以下几部分主要内容
①	硬件系统的检测和初始化程序
②	外部中断和内部中断的中断例程
③	用于对硬件设备进行I/O操作的中断例程
④	其他和硬件系统相关的中断例程。
BIOS和DOS中断例程安装过程:
①	开机后,CPU一加电,初始化(CS)=0FFFFH,(IP)=0自动从FFFF;0单元开始执行程序,在FFFF:0处有一条跳转指令,CPU执行指令后,转去执行BIOS的硬件系统检测和初始化程序。
②	初始化程序将建立BIOS所支持的中断向量,即将BIOS提供的中断例程的入口地址登记在中断向量表中,注意:对于BIOS所提供的中断例程,只需要将入口地址登记在中断向量表中即可,因为他们是固化在ROM中的程序,一直在内存中存在。
③	硬件系统检测和初始化完成后,调用int 19H 进行操作系统引导,从此交操作系统控制
④	DOS启动后,除完成其他工作外,还将它提供的中断例程转入内存中,建立中断向量。
Int 10H中断例程是BIOS提供,包含多个和屏幕输出相关的子程序
中断程序内部用传递进来的参数决定执行那个子程序,BIOS和DOS中用ah传递内部子程序的编号。 如mov 4c00H   编号为4c   其中00为返回值。

第十四章 端口

在PC机中,和CPU通过总线项链的芯片除各种存储设备外,还有以下三种
①	各种接口卡比如网卡 上的接口芯片,他们控制接口卡进行工作
②	主板上的接口芯片,CPU通过他们对部分外设进行访问。
③	其他芯片,用来存储相关的系统信息或者相关输入输出处理。
这些芯片都有一组可由CPU读写的寄存器。都与CPU总线相连,通过控制线发出端口命令
将这些寄存器都当做端口,建立统一的端口地址空间。
CPU可以直接读取①CPU内部寄存器②内存单元③端口  三处的数据
端口所在的芯片和CPU通过总线项链,故端口地址和内存地址一样,通过地址总线传送。
CPU最多可以定位64个不同的端口,端口地址从0————65535
端口的读写只有两条指令 in和out,只能用ax或者al存放读入或者要写入的数据。访问8位端口是用al  访问16位端口时用ax  
对0————255以内端口读写时  in al,20H从20H端口读入 out 20H,al 写入
对255————65535读写时,端口号放在dx中  mov dx,3f8h   in  al,dx   out  dx,al
CMOS RAM芯片简称CMOS 特征如下
①	包含一个实时钟和一个有128个存储单元的RAM存储器
②	该芯片靠电池供电,所以关机后内部的实时钟仍工作,RAM钟信息不丢失
③	128字节RAM中 内部实时钟占用0—0dh单元保存时间信息,其余大部分用于保存系统配置信息。共系统启动时BIOS程序读取
④	该芯片内部只有两个端口 70H 71H 
⑤	70H为地址端口,71H为数据端口,  CPU对CMOS RAM读写分两步 一将N号单元地址 n送进端口70H  二 从端口71H读取n号单元的内容。
Shl和shr是逻辑移位指令。Shl为逻辑左移指令功能①将寄存器或者内存单元中的数据向左移动②将最后移出的一位写入CF中。③最低位用0补充。
Mov al,01001000B  shl al,1  执行后(al)=10010000B,CF=0
如果移位数大于1时,必须将移动位数存放在cl中  mov al,01010001B  mov cl,3  
Shl al,cl  执行后(al)=10001000B  CF=0
将X逻辑左移一位,相当于执行X=X*2  将X逻辑右移一位(shr)执行X=X/2
加法和位移实现计算(ax)=(ax)*10      提示(ax)*10=(ax)*2+(ax)*8
CMOS RAM中存放信息单元:  秒0   分2  时4   日7   月8   年9  这六个信息的长度都为1字节。以BCD码存放。BCD码0——9和二进制码一样。当表示26 ,用BCD码表示为 0010 0110  一个字节可以表示两个BCD码  
BCD码+30H=十进制数对应的ASCII码

第十五章 外中断

外设的输入不直接送入内存和CPU众,而是送入相关的接口芯片的端口中。CPU向外设的输入也是先送入端口中,再由相关芯片送到外设。CPU通过端口与外部设备联系。
外中断源一共分为两类  一,可屏蔽中断  二 不可屏蔽中断。
	一,可屏蔽中断 cpu可以不响应。当CPU检测到可屏蔽中断信息时,如果IF=1,则相应,引发中断过程。如果IF=0(有其他中断过程正在进行,因为中断过程第二部设置IF=0 TF=0)则可以不响应
中断过程中设置IF为0的原因是在进入中断处理程序后,禁止其他的可屏蔽中断。
8086CPU提供的设置IF的指令   sti  设置IF=1   cli 设置IF=0
	二,不可屏蔽中断。8086CPU不可屏蔽中断的中断类型码固定为2,所以中断过程中不需要中断类型码,不可屏蔽中断的中断过程为:①标志寄存器入栈,IF=0 TF=0 ②CS IP入栈③ (IP)=(8)  (CS)=(0AH)
几乎所有由外设引发的外中断,都是可屏蔽中断。
键盘按键按下由芯片产生的扫描码送入主板相关接口芯片寄存器,其端口是60H。松开同样。
一般讲按下一个键时产生的扫描码成为通码,松开时的扫描码叫断码。长度一字节。通码第七位为0,断码第七位为1.  断码=通码+80H  引发中断类型码为9的可屏蔽中断。
BIOS提供了int 9中断例程。用来进行基本的键盘输入输出处理①读出60H端口的扫描码②如果是字符键的扫描码,将该扫描码和它对应的字符码(ASCII码)送入内存中的BIOS键盘缓冲区。如果是控制键和切换键的扫描码,则转换为状态字节写入内存中存储状态字节的单元、
在BIOS键盘缓冲区中,一个键盘输入用一个字单元存放,高位字节存放扫描码,低位字节存放字符码。
 















[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
点赞3
打赏
分享
最新回复 (18)
雪    币: 274
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
绿色黄瓜 2012-8-2 09:05
2
0
汇编我当初还是看小甲鱼的视频入的门呢
雪    币: 130
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
约翰Simith 2012-8-2 10:36
3
0
学习了!
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
霞光满树 2012-8-2 16:43
5
0
你看的好快啊。我也在看,才看两章节。好书一本呢。
雪    币: 54
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
七号梧桐 2012-8-2 18:57
6
0
呵呵。。先大致看一遍,反正这都不是学一次就能精通的东西。
雪    币: 66
活跃值: (19)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lucaslzx 2012-8-4 11:18
7
0
我买了一本汇编语言程序设计,里面讲的几乎都是16位汇编,唉,现在都是64位的世界了,买来后悔
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zffwsflove 2012-8-4 14:59
8
0
好书值得阅读
雪    币: 0
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zffwsflove 2012-8-4 15:01
9
0
外设的输入不直接送入内存和CPU众,而是送入相关的接口芯片的端口中。CPU向外设的输入也是先送入端口中,再由相关芯片送到外设。CPU通过端口与外部设备联系。
外中断源一共分为两类  一,可屏蔽中断  二 不可屏蔽中断。
  一,可屏蔽中断 cpu可以不响应。当CPU检测到可屏蔽中断信息时,如果IF=1,则相应,引发中断过程。如果IF=0(有其他中断过程正在进行,因为中断过程第二部设置IF=0 TF=0)则可以不响应
中断过程中设置IF为0的原因是在进入中断处理程序后,禁止其他的可屏蔽中断。
8086CPU提供的设置IF的指令   sti  设置IF=1   cli 设置IF=0
  二,不可屏蔽中断。8086CPU不可屏蔽中断的中断类型码固定为2,所以中断过程中不需要中断类型码,不可屏蔽中断的中断过程为:①标志寄存器入栈,IF=0 TF=0 ②CS IP入栈③ (IP)=(8)  (CS)=(0AH)
几乎所有由外设引发的外中断,都是可屏蔽中断。
键盘按键按下由芯片产生的扫描码送入主板相关接口芯片寄存器,其端口是60H。松开同样。
一般讲按下一个键时产生的扫描码成为通码,松开时的扫描码叫断码。长度一字节。通码第七位为0,断码第七位为1.  断码=通码+80H  引发中断类型码为9的可屏蔽中断。
BIOS提供了int 9中断例程。用来进行基本的键盘输入输出处理①读出60H端口的扫描码②如果是字符键的扫描码,将该扫描码和它对应的字符码(ASCII码)送入内存中的BIOS键盘缓冲区。如果是控制键和切换键的扫描码,则转换为状态字节写入内存中存储状态字节的单元、
在BIOS键盘缓冲区中,一个键盘输入用一个字单元存
雪    币: 54
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
七号梧桐 2012-8-4 22:11
10
0
呵呵,正在看Windows环境下32位汇编语言程序设计].罗云彬.第三版    慢慢来吧,多学总比不学好。
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ygd 2012-8-5 12:13
11
0
学习了,很基础很好的一本书
雪    币: 54
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
七号梧桐 2012-8-6 21:47
12
0
正在看、。。。
雪    币: 33
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
anqi 2012-8-7 11:30
13
0
之前看过,确实是很好的一本讲汇编的书
雪    币: 42
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
星奥 2012-8-7 21:58
14
0
底层东西太繁琐
不过要想牛,必须学
雪    币: 1097
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Potato丶 2012-8-8 11:05
15
0
嗯。这读书笔记真的很不错。。支持一下!
雪    币: 249
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
风雨声 2012-8-8 11:11
16
0
是怎么在一周的时间内看完的王爽《汇编》的???我专心花了一个月,才弄差不多的。不过膜拜下,哈哈。
雪    币: 54
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
七号梧桐 2012-8-8 17:04
17
0
呵呵。看的略显仓促。毕竟重头戏在罗云彬的那本32位汇编。
雪    币: 33
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
林大人 2012-8-9 11:24
18
0
我也看完了,但是发现不知道能干什么
雪    币: 54
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
七号梧桐 2012-8-12 12:47
19
0
继续 win32中。。。。
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
会飘的云 2012-8-12 13:32
20
0
要是谁出本外挂书就猛了
游客
登录 | 注册 方可回帖
返回