汇编语言
汇编指令:机器指令的助记符
mov ax,bx
寄存器:CPU中可以存储数据的器件
ax:寄存器的代号
bx:寄存器的另一个代号
汇编语言的组成
汇编指令(机器码的助记符) 伪指令(由编译器执行) 其他符号(由编译器识别)
CPU对存储器的读写:
地址信息 控制信息 数据信息
总线:地址总线 数据总线 控制总线
8086CPU:
1byte=8bit
随机存储器和只读存储器(ROM)
装有BIOS的ROM
BIOS:Basic input/output system ,基本输入输出系统
寄存器(CPU互作原理)
通用寄存器
字在寄存器中的存储
段地址*16+偏移地址=物理地址
CPU:运算器 控制器 寄存器(这些器件靠内部总线相连)
8086CPU有14个寄存器 它们的名称为:
ax,bx,cx,dx,si,di,sp,bp,ip,cs,ss,ds,es,psw;
通用寄存器
8086CPU所有的寄存器都是16位的,可以存放两个字节。
ax,bx,cx,dx 通用寄存器
ax可分为ah和al;
....
8086pc机的内存地址空间
主存储器地址空间
显存地址空间
各类ROM地址空间
字在寄存器中的存储
高8位,低8位
汇编指令不区分大小写
mov ax,18 ax=18
mov ah,78 ah=78
add ax,8 ax=ax+8
mov ax,bx ax=bx
add ax,bx ax=ax+bx
段地址*16+偏移地址=物理地址
段地址*16==二进制数左移4位
一个数据的二进制形式左移N位,相当于该数据2的N次方位
段的概念
内存并没有分段,段的区分来自CPU
将若干地址连续的地址单位看做一个段,用段地址*16定位段的起始地址(基础地址),用偏移地址定位段中的内存地址
CPU访问内存单元时,必须向内存提供内存单元的物理地址
CPU可以用不同的段地址和偏移地址得到相同的物理地址
段寄存器
段寄存器就是提供段地址的
8086CPU有4个段寄存器:
CS(代码段寄存器) DS(数据段..) SS(堆栈段..) ES(附加段..)
CS为代码段寄存器 IP为指令指针寄存器
从cs:IP指向内存单元读取指令,读取的指令进入指令缓冲器
IP=IP+所读取指令的长度,从而指向下一条指令
执行指令。转到步骤1,重复过
启动时,cs和IP被设置为cs=ffffh,ip=0000h
cpu从内存ffff0h单元中读取指令执行
ffff0h单位中的指令是8086pc机开机执行的第一条指令
如何修改AX中的值?
mov ax,123 mov指令不能用于设置cs和IP的值,8086CPU没有提供这样的功能
8086CPU为cs和IP提供了另外的指令来改变他们的值:转移指令
同时修改cs和IP的内容:
jmp 段地址:偏移地址
jmp 2AE3:3
JMP 3:0B16
功能:用指令中给出的段地址修改cs ,偏移地址修改IP
代码段
CPU只认被cs:ip 指向的内存单元中的内容为指令。
所以要将cs:ip指向所定义的代码段中的第一条指令的首地址
段地址在8086CPU的寄存器中存放。8086CPU要访问内存时,有段寄存器提供的内存单元的段地址。8086CPU有4个段寄存器,其中cs用来存放指令的段地址
cs存放指令的段地址,IP存放指令的偏移地址
CPU将cs:ip指向的内容当作指令执行
debug的使用
R:查看,改变CPU寄存器的内容
D:查看内存中的内容
E:改写内存中的内容
U:将内存中的机器指令翻译成汇编语言
T:执行一条机器指令
A:以汇编指令的格式在内存中写入一条机器指令
a 1000:0
mov ax,1
mov ax,ax
jmp 1000:0 循环
寄存器(内存)
内存中字的存储
ds和address
字的传送
mov add sub指令
数据段
栈
CPU提供的栈机制
栈顶超界的问题
push pop指令
栈段
8086CPU有一个ds寄存器,通常用来存放要访问的数据的段地址
mov bx,1000H
mov ds,bx
mov al,[0] [0]表示的是偏移地址
执行指令时,8086CPU自动取ds中的数据为内存单元的段地址
数据--》通用寄存器--》段寄存器
e 1000:0 23 11 22 66
d 1386:100
mov 指令默认的段地址在ds寄存器中
[address]表示是一个便宜地址为address的内存单元
mov add sub 是具有两个操作对象的指令,jmp是具有一个操作对象的指令
第一个程序(UltraEdit编辑器)
源程序:
编辑 编译 连接 .EXE的执行
可执行文件中的程序装入内存并执行
可执行文件中包含两部分内容:
程序和数据
相关的描述信息
assume cs:codesg
伪指令:没有对应的机器码的指令,最终不被CPU所执行
codesg segment
伪指令由编译器来执行的指令,编译器根据伪指令来进行相关的编译互作
start:mov ax,1234H
汇编指令
mov bx,1456H
add ax,bx
add ax,ax
mov ax,4c00h
int 21h
codesg ends
end ;结束对源程序的编译
segment和ends是一对使用的伪指令,这儿是在写可被编译器编译的汇编程序时必须要用到的一对伪指令
segment和ends的功能是定义一个段,segment说明一个段的开始,ends说明一个段的结束
一个段必须有一个名称来标识,使用格式为:
段名 segment
段名 ends
定义一个段
一个汇编程序是由多个段组成,这些段被用来存放代码、数据或当作栈空间来使用
一个有意义的汇编程序中至少要有一个段,这个用来存放代码
assume 假设 寄存器与段的关联假设
它假设某一段寄存器和程序中的某一个用segment...ends定义的段相关联
汇编源程序:
伪指令 (编译器处理)
汇编指令(编译为机器码)
标号
一个标号指代一个地址
codesg :放在segment的前面,作为一个段的名称,这个段的名称最终将被编译、连接程序处理为一个段的段地址
定义一个段 abc segment
实现处理任务 mov ax,2
add ax,ax
add ax,ax
程序结束
abc ends
段与段寄存器关联
end
程序的返回
DOS是一个单任务操作系统,一个程序结束后,将控制权交给另一个程序执行
mov ax,4c00h
int 21h ;int:中断指令
语法错误和逻辑错误
语法错误
程序在编译时被编译器发现的错误无
逻辑错误
程序在编译时不能表现出来的、在运行时发生的错误
assume cs:abc
abc segment
mov ax,2
add ax,ax
add ax,ax
mov ax,4c00h
int 21h
abc ends
end
debug可以将程序加入内存,设置cs:ip指向程序的入口,但debug并不放弃对CPU的控制,这样,我能就可以使用debug的相关命令来单步执行程序,查看每条指令的执行结果
程序加载后,ds中存放着程序所在内存的段地址,这个内存区的偏移地址为0,则程序所在的内存地址为ds:0
这个内存区的前256个字节中存放时PSP,DOS用来和程序进行通信
从256字节处向后的空间存放的是程序
所以我们从ds中可以得到PSP的段地址sa,PSP的偏移地址为sa*16+0
因为PSP占256(100H)字节所以
用U命令查看一下其他指令
用T命令单步执行程序中的每一条指令,并观察每条指令的执行结果
到了int 21,我们要用p命令执行
int 21执行后,放回debug中,程序正常结束
什么是[bx]
assume cs:codesg
codesg segment
fishcc:mov ax,2000H
mov ds,ax
mov al,[0] 将0数值传给al
mov bx,0
mov al,[bx] 将0位地址的数据传给al
mov bl,[1]
mov cl,[2]
mov dl,[3]
mov ax,4c00h
int 21h
codesg ends
end fishcc