汇编学习
汇编语言
机器语言是机器指令的集合
机器指令是一台机器可以正确执行的命令
机器指令有一串二进制表示
汇编语言的主题是汇编指令
汇编指令和机器指令的差别在于指令的表示方法上:
汇编指令是机器指令便于记忆的书写格式
汇编指令是机器指令的助记符
MOVAX,BX 将寄存器BX的内容送到AX中
寄存器:CPU中可以存储数据的期间,一个cpu中有多个寄存器
流程:汇编指令---编译器---机器码----计算机
汇编指令是机器码的助记符
伪指令--由编译器执行
CPU是计算机的核心部件,他控制整个计算机的运作并进行运算,要想让一个cpu工作,就必须向他提供指令和数据
指令和数据在存储器中存放,离开了内存,性能再好的cpu也无法工作
指令和数据的表示:
计算机中的数据和指令,存储在内存或磁盘上
数据和指令,都是二进制信息
问题:二进制信息1000001010100是数据,还是指令
二进制是指令还是数据有cpu决定:
当二进制信息是数据是-->被转换成了十六进制
当二进制信息是指令时-->被转换成了汇编代码
数据的表示:
二进制:B 十六进制:H 八进制:O 十进制: D
计算机中的存储单元:
存储器被划分为诺干个存储单元,背个存储单元从0开始顺序编号
总线:数据总线(cpu玉内存或其他器件之间的数据传送是通过数据总线来进行的,数据总线的宽度决定了cpu和外界的数据传送速度),地址总线(cpu通过地址总线来指定存储单元),控制总线(cpu通过控制总线对外部器件进行控制)
CPU要想进行数据的读写,必须和外部器件进行三类信息的交互:
存储单元的地址(地址信息);器件的选择,读或写命令(控制信息);读或写的数据(数据信息)
汇编指令 MOV AL,[3]
首先地址线寻址,找到内存单元3,之后控制线发出控制信息读,然后数据线将3内存单元的信息存放到了AL中
什么是内存地址空间:
CPU的总线宽度为N,寻址空间为2的n,例如8086CPU的地址总线宽度为20,那么可以寻址1mb个内存单元。其内存地址空间为1MB
RAM:能读能写,掉电之后清除
ROM:只能读(BIOS)
将各类存储器看做一个裸机存储器--统一编址
所有的物理存储器被看做一个由诺干个存储单元组成的逻辑存储器
每个物理存储器在这个逻辑存储器中占-you一个地址段,即一段地址空间
CPU在这段地址空间中读写数据,实际上就是在相对应的物理存储器中读写数据
8086PC机为例
访问寄存器和内存=
cpu的组成:
运算器进行信息处理;
寄存器进行信息存储
控制器协调各种器件进行工作
内部总线时间cpu内各个器件之间的联系
寄存器是cpu内部信息存储单元
8086cpu有14个寄存器
通用寄存器:AX,BX,CX,DX
变址寄存器:SI,DI
指针寄存器:SP,BP
指令指针寄存器:IP
段寄存器:CS,SS,DS,ES
标志寄存器:PSW
共性:所有寄存器都是16位的可以存储两字节的数据
一个寄存器存储一个16为的数据
最大值FFFFH
问题:8086上一代cpu中的寄存器都是8位的,如何保证程序的兼容性。
方案:通用寄存器均可分为两个独立的8为寄存器使用
细分为:AX分为:AH和AL
mov和add指令:
mov ax,18 将18送入AX
mov ah,78将78送入ah中
add ax,8 将寄存器ax中的数值加上8
mov ax,bx 将寄存器bx中的数据送入寄存器ax中
add ax,bx 将ax,bx中的内容相加,结果存在ax中
在进行指令相加时溢出为会被丢掉
CPU访问内存单元时要给出内存单元地址
所有的内存单元构成的存储空间是一个一维线性空间
每一个内存单元在这个空间中都有唯一的地址,这个唯一的地址值称为物理地址
问题:实际上8086有20为地址总线,可传送20为地址,寻址能力为1m,但8086是16位结构的cpu 运算器一次最多可以处理16位的数据,寄存器的最大宽度为16位,那么8086如何处理在寻址空间上的这个矛盾?
方法:
用两个16位地址段,偏移地址合成一个20位的物理地址
物理地址=段地址x16+偏移地址
内存并没有分段,段的划分来自cpu
段地址很重要--用专门低寄存器放段地址
4个段寄存器:
CS -代码段寄存器
DS -数据段寄存器
SS -栈寄存器
ES-附加段寄存器
debug的使用
r-查看,改变cpu寄存器内容
d:查看内存中的内容
e:改变内存中的内容
u:将内存中的机器指令翻译成汇编指令
a:以汇编指令的格式在存储中写机器指令(这里我们写的是汇编指令,但是在实际的内存中,被编译成了机器码存储到了 内存中)
t:执行机器指令(执行CS:IP处的机器代码)
e 地址 数据-写入
d 地址 -查看
u 地址 -查看代码
q:退出
CS 是代码执行的段地址
IP 是代码执行的偏移地址
CS 和IP寄存器
CS:代码段寄存器
IP:指令指针寄存器
CS:IP:CPU将内存中cs:ip
指向的内容当作指令执行
CS和IP通过加法器转换成20位地址,然后定位到内存中代码存放的地方
8086PC工作过程的简要描述:
从CS:IP指向内存单元读取指令,读取的指令进入指令缓存器;
IP=IP+所读取指令的长度,从而指向下一条指令
那么,所读指令的字节数应该怎么判断呢?
汇编指令长度与寻址方式有关,规律或原则如下:
一、没有操作数的指令,指令长度为*1*个字节
二、操作数只涉及寄存器的的指令,指令长度为*2*个字节
如:*mov bx,ax*
三、操作数涉及内存地址的指令,指令长度为*3*个字节
如:*mov ax,ds:[bx+si+idata]*
四、操作数涉及立即数的指令,指令长度为:寄存器类型*+1*
*8*位寄存器,寄存器类型*=1*,如:*mov al,8*;指令长度为*2*个字节
*16*位寄存器,寄存器类型*=2*,如:*mov ax,8*;指令长度为*3*个字节
问题:内存中有数据B8 23 01 BB 03 00 89 D8 01 D8 究竟用作一般数据,还是用作指令?
cpu将CS:IP 指向的内存单元中的内容看作指令
事实:执行何处的指令,取决于CS :IP 指向的物理地址
应用:可以通过改变CS ,IP中的内容,来控制CPU要执行的目标指令
问题如何改变cs:ip的值
方法一:用指令修改
mov cs 2000h 但是这种方法是不行的
jmp转移指令
同时修改cs和ip的内容:
jmp 段地址 : 偏移地址
仅修改IP的内容:
jmp某一合法寄存器
jmp ax (类似于mov IP ax)
内存中字的存储:
对8086cpu中16位作为一个字
解决问题:CPU从内存单元中药读取数据
CPU要读取一个内存单元的时候,必须先给出这个内存单元的地址
原理:在8086CPU中,内存地址由段地址和偏移地址组成
解决方法:DS和[address]配合
用DS寄存器存放要访问的数据的段地址,偏移地址用[...]的形式直接给出
mov bx,1000h
mov ds,bx
mov al,[0]
将10000H(1000:0)中的数据读到al中
--------------------
mov bx,1000h
mov ds,bx
mov [0],al
将al里面的数据放到[1000:0]中
要给段寄存器赋值改值的话必须通过通用寄存器去间接改变
mov bx,1000H
mov ds,bx
8086不支持将数据直接送入段寄存器中
CS是值CPU执行的当前指令的段地址,DS是数据开始的段地址
表示一个物理地址,其中段地址和偏移地址不是固定的
栈是一种只能在一端进行插入或删除操作的数据结构
栈有两个基本的操作:入栈和出栈
出栈:从栈顶取出一个元素
栈顶的元素总是最后入栈,需要出栈时,又最先被从栈中取出
栈的操作规则:LIFO 后进先出
CPU提供的栈机制:
现在的CPU中都有栈的设计
8086CPU提供相关的指令,支持用栈的方式访问内存空间
基于8086CPU的编程,可以将一段内存当作栈来使用
PUSH入栈和POP出栈指令
push ax:将ax中的数据送入栈中
pop ax:从栈顶取出数据送入ax,以字为单位对栈进行操作
cpu如何知道一段空间被当作栈使用?
cpu由两个与栈相关的寄存器:栈段寄存器ss 存放栈顶的段地址 栈顶指针寄存器SP 存放栈顶的偏移地址
任意时刻:ss:sp指向栈顶元素
cpu只是知道栈顶在何处,不知道程序安排的栈空间有多大
push ,pop 实质是内存传送指令,可以在寄存器和内存之间传送苏剧,与mov指令不同的是
汇编语言程序--->编译器----->机器码
伪指令:没有对应的机器码的指令,最终不被cpu所执行
伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作
汇编指令:对应由机器码的指令,可以被编译为机器指令,最终被cpu执行
段定义:
一个汇编程序是由多个段组成的,这些段被用来存放代码,数据或者当作栈空间来使用
一个有意义的汇编程序中至少要有一个段,这个段用来存放代码
定义程序中的段:每个段都需要有段名
段名 segment --段的开始
......
段名 ends ---段的结束
assume(假设)
含义是假设某一段寄存器和程序中的某一个用segment ---ends定义的段相关联
assume cs:codesg指cs寄存器与codesg关联,将定义的codesg当作程序的代码段使用
inc:
loop指令:实现循环(计数型循环)
指令的格式:loop 标号
cpu执行loop指令时要进行的操作:
1.(cx)=(cx)-1
2.判断cx中的值:不为零则转至标号出执行程序,如果为零则向下执行
要求:cx中要提前存放循环次数,应为cx影响这loop指令的执行结果
要定义一个标号
段前缀的使用
inc 连续累加
mov bx,0
inc bx //这是bx就是1
accume cs:code
code segment
mov ax,0ffffh
mov ds,ax ##设置数据段地址
mov bx,0 ##初始化bx寄存器,这个寄存器用于存放地址单元块的标号
mov dx,0 ##初始化bx寄存器,这个寄存器用于存放各个地址单元的相加值
assume cs:code
code segment
编程计算一下8个数据的和,结果存在ax寄存器中:
0123h,0456h,0789h,0abch,0defh,0fdeh,0987h,0387h
解决方案:
assume cs:code
code segment
dw 0123h,0456h,0789h,0abch,0defh,0fdeh,0987h,0387h
start: mov bx,0
mov ax,0
mov cx,0
s: add ax,cs:[bx]
add bx,2
loop s
mov ax,4c00h
int 21h
code ends
end start
效果:程序加载后cs:ip指向程序的入口

浙公网安备 33010602011771号