最近将汇编粗略的复习了下,作个简单记录:
1,基础知识
2,寄存器
3,寄存器(内存访问)
4,第一个程序
5,[BX]和loop指令
6,包含多个段的程序
。。。
第一章 基础知识
1,用汇编语言编写程序的过程如下图所示:
2,汇编语言发展至今,有以下3类指令组成:
汇编指令:机器码的助记符,有对应的机器码。
伪指令:没有对应的机器码,由编译器执行,计算机并不执行。
其它符号:如+、-、*、/等,由编译器识别,没有对应的机器码。
汇编语言的核心是汇编指令,它决定了汇编语言的特性。
3,每一种CPU都有自己的汇编指令集。CPU可以直接使用的信息在存储器中存放。
4,在存储器中指令和数据没有任何区别,都是二进制信息。存储单元从零开始顺序编号。一个存储单元可以存储8个bit,即8位二进制数。
5, 1Byte=8bit 1KB=1024B 1MB = 1024KB 1GB = 1024MB
6,每一个CPU芯片都有许多管脚,这些管脚和总线相连。也可以说,这些管脚引出总线。一个CPU可以引出3种总线的宽度标志了这个CPU的不同方面的性能:
地址总线的宽度决定了CPU的寻址能力;
数据总线的宽度决定了CPU与其它器件进行数据传送时的一次数据传输量;
控制总线的宽度决定了CPU对系统中其它器件的控制能力。
7,CPU系统中各类存储器看作一个逻辑存储器,如下图所示。
8,不同的计算机系统的内存地址空间的分配情况各不相同。8086PC机内存地址空间分配情况如下图所示:
2.第二章 寄存器
1,一个典型的CPU由运算器、控制器、寄存器等器件构成。运算器进行信息处理;寄存器进行信息存储;控制器控制各种器件进行工作;内部总线连接各种器件,在它们之间进行数据的传送。
2,8086 CPU有14个寄存器,每个寄存器都有一个名字:AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW
3,通用寄存器:AX、BX、CX、DX,用于存储一般性的16位数据。这4个寄存器又可以各自分为两个独立的8位寄存器来用:AH和AL;BH和BL、CH和CL、DH和DL。数据存储情况如下所示:
4,字节:记为byte,一个字节由8个bit组成,可以存储在8位寄存器中。字:记为word,一个字由两个字节组成,这两个字节分别称为这个字的高位字节和低位字节。
5,几条汇编指令举例:
6,16位结构的CPU可以按照如下描述:
运算器一次最多可以处理16位的数据;
寄存器的最大宽度为16位;
寄存器和运算器之间的通路为16位。
7,8086CPU有20位地址总线,可以传送20位地址,达到1MB寻址能力。而8086CPU又是16位结构,所以,8086CPU采用一种在内部用两个16位地址合成的办法来形成一个20位的物理地址,相关部件的逻辑结构如下图说所示:
1)CPU中的相关部件(CS和IP)提供两个16位的地址,一个称为段地址,另一个称为偏移地址;
2)段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;
3)地址加法器将两个16位地址合成为一个20位的物理地址:物理地址 = 段地址x 16 + 偏移地址
4)地址加法器通过内部总线将20位物理地址送入输入输出控制电路;
5)输入输出控制电路将20位物理地址送上地址总线;
6)20位物理地址被地址总线传送到存储器。
8,CS和IP是8086CPU中两个最关键的寄存器,它们指示了CPU当前读取指令的地址。CS为代码段寄存器,IP为指令指针寄存器。在8086CPU机中,任意时刻,设CS中的内容为M,IP中的内容为N,8086CPU将从内存Mx16+N单元开始,读取一条指令并执行。
9,8086CPU的工作过程简述如下:
Step1: 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器;
Step2:IP=IP+所读取指令的长度,从而指向下一条指令;
Step3:指令执行。转至step1,重复这个过程。
10,修改CS、IP的指令
a)jmp 段地址:偏移地址 -> 用指令中给出的段地址修改CS,偏移地址修改IP。
b)Jmp 某一合法寄存器 -> 仅修改IP的内容
第三章 寄存器(内存访问)
1,子单元,即存放一个字型数据(16位)的内存单元,由两个地址连续的内存单元组成。高地址内存单元中存放字型数的高位字节,低地址内存单元中存放字型数据的低位字节。起始地址为N的字单元简称为N地址字单元。
2,DS和[address]。8086CPU有一个DS寄存器,通常用来存放要访问数据的段地址。用mov指令访问内存单元,可以再mov指令中只给出单元的偏移地址,此时,段地址默认在DS寄存器中。示例代码如下:将1000H(1000:0)中的数据读入到al中。至于为何不直接将1000H送入ds,即mov ds,1000H,这是8086CPU硬件设计的问题。
mov bx,1000H
mov ds,bx
mov al,[0]
3,mov指令
mov:寄存器,数据
mov:寄存器,寄存器
mov:寄存器,内存单元
mov:段寄存器,内存单元
mov:内存单元,寄存器
mov:内存单元,段寄存器
mov:段寄存器,寄存器
mov:寄存器,段寄存器
4,add指令
add:寄存器,数据
add:寄存器,寄存器
add:内存单元,寄存器
add:寄存器,内存单元
4,sub指令
sub:寄存器,数据
sub:寄存器,寄存器
sub:内存单元,寄存器
sub:寄存器,内存单元
5,jmp指令
jmp:段地址:偏移地址 用段地址修改CS 用偏移地址修改IP
jmp:寄存器,只用寄存器的内容修改IP
6,在内存和寄存器之间传送字型数据时,高地址单元和高8位寄存器、低地址单元和低8位寄存器相对应。
7,mov、add、jmp是具有两个操作对象的指令。jmp是具有一个操作对象的指令。
8,栈:LIFO(Last In First Out,后进先出)。
9,8086CPU出栈入栈都是以字为单位进行的;在SS、SP中存放栈顶的段地址和偏移地址;任意时刻,SS:SP指向栈顶元素;push指令(入栈)和pop指令(出栈)执行时,CPU从SS和SP中得到栈顶的地址;8086CPU只记录栈顶,栈空间的大小我们要自己管理;push、pop实质上是一种内存传送指令。
10,push ax 由一下两步完成
1)SP=SP-2
2)将ax中的内容送入SS:SP指向的内存单元
11,pop ax
1)将SS:SP指向的内存单元中的内容送入ax
2)SP=SP+2
12,push/pop其它
push 寄存器
pop 寄存器
push 段寄存器
pop 段寄存器
push 内存单元
pop 内存单元
只给出内存单元的偏移地址,段地址在指令执行时从ds中获得。
13,段的综述
++++++++++++++++++++++++
为了编程的方便,人为的将一段内存定义为一个段:用一个段地址指示段,用偏移地址访问段内的单元。
比如,用一个段存放数据,将它定义为“数据段”;用一个段存放代码,将它定义为“代码段”;用一个段当作栈,将它定义为“栈段”。
对于数据段,将它的段地址放在DS中,用mov、add、sub等访问内存单元的指令时,CPU就将我们定义的数据段中的内容当作数据来访问;
对于代码段,将它的段地址放在CS中,将段中第一条指令的偏移地址放在IP中,这样CPU就将执行我们定义的代码段中的指令;
对于栈段,将它的段地址放在SS中,将栈顶单元的偏移地址放在SP中,这样CPU在需要进行栈操作的时候,比如执行push、pop指令等,就将我们定义的栈段当作栈空间来用。
可见,不管我们如何安排,CPU将内存中的某段内容当作代码,是因CS:IP指向了那里;CPU将某段内存当作栈,是因为SS:SP指向了那里。我们要清楚,什么是我们的安排,以及如何让CPU按我们的安排行事。
一段代码,可以既是代码的存储空间,又是数据的存储空间,还可以是栈空间,也可以什么也不是。关键在于寄存器的设置,即CS、IP,SS、SP,DS的指向。
++++++++++++++++++++++++
第四章 第一个程序
1,segment 和ends是一对成对使用的伪指令,用于定义一个段。segment说明一个段开始,ends说明一个段结束。如下的Xxx为段的名称。
Xxx segment
...
Xxx ends
2,伪指令end是一个汇编程序的结束标记。注意区别ends(与segment是成对使用的)。
3,伪指令assume含义为“假设”,即假设某一段寄存器和程序中的某一个用segment...ends定义的段相关联。
4,与结束相关的概念
5,汇编程序从写出到执行的全部过程如下:
第五章 [BX]和loop指令
1,mov ax, [bx] 功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将SA:EA处的数据送入ax中。即:(ax)=((ds)*16+(bx))。
2,mov [bx], ax 功能:bx中存放的数据作为一个偏移地址EA,段地址SA默认在ds中,将ax中的数据送入内存SA:EA处。即:((ds)*16+(bx))=(ax)。
3,用cx和loop指令相配合实现循环功能的程序框架如下:
mov cx, 循环次数
s:
循坏执行的程序段
loop s
4,loop指令的格式是:loop标号,CPU执行loop指令的时候,要进行两个操作:
Step1:(cx)=(cx)-1;
Step2:判断cx中的值,不为零则转至标号处执行程序,如果为零则向下执行。
第六章 包含多个段的程序
1,段名相当于一个标号,它代表了段地址。所以,“mov ax,data”就是将名为data的段的段地址送入ax.
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
stack ends
code segment
start: mov ax,stack
mov ss,ax
mov sp,16 ;将设置栈顶ss:sp指向stack:16
mov ax,data
mov ds,ax ;ds指向data
mov bx,0 ;ds:bx指向data段中第一个单元
mov cx,8
s: push [bx]
add bx,2
loop s ;将以上代码段0-16单元中的8个字符型数据依次入栈
mov bx,0
mov cx,8
s0: pop [bx]
add bx,2
loop s0 ;以上依次出栈8个字符型数据到代码段0-16单元中
mov ax,4c00H
int 21h
code ends
end start ;指名程序的入口在start处
。。。。。。
参考:
1,《汇编语言》-王爽,清华大学出版社
2, 汇编网