汇编语言
汇编指令 =》通过编译器 =》010100101
伪指令 =》告诉翻译软件也就是编译器,这里怎么翻译,那里怎么翻译,有编译器执行,没有对应的机器指令
符号体系 =》没有对应的机器指令,由编译器执行
机器指令和汇编指令的关系?
通过编译器可以一一对应
CPU 通过指令来控制整个计算机
指令和数据
CPU 在工作时 需要对 指令和数据进行区分
指令和数据是以什么形式存放在内存中的?
以二进制形式存放在内存中的
内存也叫存储单元
最小的存储单位是字节
1字节(Byte) = 2个16进制数字 = 8个2进制数字
1Byte = 8bit
对字节(存储单元)进行编号
CPU对于内存的读写是通过导线和内存进行传输数据,这些导线和平常电子元件常见
铜线一样只是做的细罢了,这些导线在一起通常成为总线,为了区分这些总线传输的
容逻辑上分为3类,地址总线(传输的是内存地址)、控制总线(传输的是控制命令
)、数据总线(传输的是控制的数据)
ROM 只允许读取,不允许写入,不通电的情况下里面的数据还是保持的
RAM 运行写入,允许读取,电没了就没了
通用寄存器 一般存放数据
通用寄存器表示形式 = AX-4E20
AX = AH + AL H = high 高(前两位) L = low 低(后两位)
BX = BH + BL
CX = CH + CL
DX = DH + DL
寄存器是相互独立的
AH 和 AL 是没有关系的
move ax,bl
这一行代码是错的,8位寄存器不能写到16位的寄存器中
注意寄存器能够写的最大值 一个字节是 255 = FF
AX = 65535 = FFFFH
表示地址信息的寄存器
左边:段地址 右边:偏移地址
虚拟 8086CPU 20根地址线 20bit 寄存器16位,只有16bit
位数不匹配,属于设计失误
补救:
物理地址 = 基础地址 + 偏移地址
基础地址 = 段地址 = 16(10H)
段地址 偏移地址
1238H C8H = 1230H * 10H + C8H
= 12300H + C8H = 123C8H
帮助理解的小例子
学校 体育馆 图书馆 16进制
0 2000 2826
我现在有2张能写4位数字的字条
第一张 第二张
0 + 2826
2000 + 826
我现在有2张能写3位数字的纸条
第一张 第二张
200 + 826 = 200(段地址)*10 + 826(偏移地址) = 2826
1.CPU中存放段地址信息的寄存器? ds es ss cs
2.CPU中存放偏移地址信息的寄存器? bp ip sp si di bx(bx可以把地址信息当做数据来存储)
3.偏移地址能够表示的最大值是多少? FFFFH
CPU是怎么区分指令和数据的?
CPU将CS:IP所组合(指向)出来的地址里面的内容全部当做指令
指令和数据存放内存中没有区别!!
指令是有长度的,可以由多个字节组成
指令执行的过程
1. CPU 从 cs:ip 所组合的地址中读取指令,将这个指令存放到指令缓冲器中
2. IP = IP + 所读指令的字节数
3. 执行指令缓存器中的内容,回到步骤1 重复这个过程
转移指令
能够修改ip或者cs 或者同时修改的指令
jmp 2000:0 前面的是ip,后面的是cs
jmp 寄存器 例:jmp ax 就等于把ax的地址赋值给ip
检测点
1.下面的3条指令执行后,CPU 几次修改了IP?都是在什么时候?最后IP中的值是多少?
move ax,bx => 指令缓存器 => 1 => 执行
sub ax,bx => 指令缓存器 => 1 => 执行
jmp ax => 指令缓存器 => 1 => 执行 => 1
答案:一共执行了4次,最后 ip = 0
call 转移指令,相当于调用方法
call cpy_Boot : --->指令缓冲器中--->ip--->
:call
move ax,1000H :IP指向move ax,1000H 将ip保存起来-->跳转到cpy_Boot方法里
move ax,4c00H
int 21H
:---------------
cpy_Boot:
move bx,1000H
move bx,1001H
ret :返回,跳转回call方法保存的ip地址所指向的指令
move cx,2000H 该指令并不会被执行
汇编程序员就是通过汇编指令修改 CPU 的寄存器中的内容控制 CPU,从而达到控制整个计算机的目的
add指令加法练习
1.写几条指令,将一段内存中连续3个字型数据累加存放到 AX 中
20000H 12H => 3412H
20001H 34H
20002H 99H => 8899H
20003H 88H
20004H FFH => EEFFH
20005H EEH
指令代码如下:
move bx,2000H
move ds,bx
move ax,0
add ax,ds:[0]
add ax,ds:[2]
add ax,ds:[4]
段地址:偏移地址
ss:sp
push ax => sp-2 => ax存放到ss:sp-2
pop ax => ss:sp存放到ax => sp+2
1. CS:IP 和指令有关
2. DS:[0] [1] ... 和数据有关
3. SS:SP 临时性数据
数据在哪里
数据的长度 字节型数据 字型数据 AX BX CX DX AH AL BH BL
数据的处理 ADD SUB
数据存放到哪里
数据是我们自己安排的
存放到哪里也是自己安排
指令在哪里也要自己安排
自由的代价:谨慎
汇编语言
汇编指令
伪指令 由编译器执行的
符号体系
1.编写源代码 源程序
2.编译(通过编译器)
3.链接
4.执行程序
loop 循环指令 CX = CX - 1 检测CX是不是等于0
循环体
CX 循环次数
loop循环的执行顺序是先执行代码,然后将CX减去1,拿CX减去1的结果与0进行比较,如果不相等则跳转到上方进行循环,如果等于0则继续执行下方的代码。
能够改变 CS:IP 的是转移指令
loop是转移指令
move ax,0
move cx,123
addNumber: add ax,236
move dx,1000H
move dx,2000H
loop addNumber // 标号 地址
move ax,4C00H
int 21H
coder ends
end
and指令 和 or指令
and指令:逻辑运算指令,按位进行 与 运算
or指令:逻辑运算指令,按位进行 或 运算
ds:[bx+5] 偏移地址的组合
inc(a) 就相当与 a:=a+1 即在本次循环是累加
si和di 偏移地址寄存器
使用方法和bx一样
ds:[bx]
ds:[bx+5]
start: move ax,data
move ds,ax
move es,ax
move si,0
move di,16 //数据从哪里来 ds:[si] 数据到哪里去 es:[di]
move cx,8
copyData: move dx,ds:[si]
move es:[di],dx
add si,2
add di,2
loop copyData
/* 第二种解决办法
start: move ax,stack
move ss,ax
move sp,32
move ax,data
move ds,ax
move es,ax
move si,0
move di,16 //数据从哪里来 ds:[si] 数据到哪里去 es:[di]
move cx,8
copyData: push ds:[si]
pop es:[di]
add si,2
add di,2
loop copyData
*/
内存访问形式
ds:[bx+si]
ds:[bx+di]
ds:[bx+si+4]
ds:[bx+di+5]
ds:[?] ds为段地址 []里面的值为偏移地址
一个字型数据占两个字节 一个字节8位
归纳1:数据可以存放在哪?
1.CPU的寄存器中
ax,bx,cx,dx ah,al bh,bl ch,cl dh,dl
2.内存中
地址信息 8086CPU
段地址信息:偏移地址信息
ds ip
es sp
ss si
cs di
bp
ds:[0] ds:[bx] ds:[si] ds:[di] ds:[bp]
//ds:[si+di] si+di是不允许这么写的
ds:[bx+si+2] ds:[bx+di] ds:[bx+si]
ss:[bp+si+2]
3.端口中
归纳2:数据的长度
字型数据 字节型数据
mov ax,1 move al,1
move bx,ds:[0] move al,bl
move ax,ds
move ax,1000
move ds,ax
inc ax
把数据当做字型数据存放到ds中 把数据当做字型数据存放到ds中
mov word ptr ds:[0],1 mov byte ptr ds:[0],222
inc word ptr ds:[bx] inc byte ptr ds:[0]
除数 8bit 16bit 存在内存单元中 或者 寄存器中
被除数 AX或者 AX和BX中
如果除数为8bit,被除数则为16bit,存放在AX中
如果除数为16bit,被除数则为32bit,AX存放低16bit,DX存放高16bit
结果:如果除数为8bit,则AL 存放 商,AH 存放余数
如果除数为16bit,则AX 存放 商,DX 存放余数
db 占1个字节
dw 占2个字节
dd 占4个字节
inc bx 将bx中的值加1
dec bx 将bx中的值减去1
转移指令
灵活性
标号处的地址 - jmp指令后的第一个字节的地址 = 位移 ;编译器
jmp 段间转移
短转移 -128 ~ 127
DFFFSET 伪指令
条件转移指令
jcxz 标号 j = jmp cx 寄存器 z = zero
if cx 等于 0 jmp 标号
nop 指令 ;CPU 什么事都不做 只是占用两个字节
ret pop ip ss:sp 字型数据 => ip sp+2
retf pop ip pop cs
jmp 位移
call 指令比jmp多做了一件事 push ip push的是第2步时已经 自加所读指令字节数 的ip
call s 与 ret 配合使用 call:push ip ret:pop ip
call far ptr s 与 retf 配合使用
call far ptr:push cs, push ip retf:pop ip pop cs
mul 乘法
8bit 一个字节 al bl mul byte ptr ds:[0] AX
16bit 2个字节 ax bx mul word ptr ds:[0] AX DX
标志位寄存器
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
OF DF IF TF SF ZF AF PF CF
运算溢出,溢出的1是存在 CF 中
CF: Carry Flag
ZF: Zero Flag
PF: Parity Flag
SF: Sign Flag
标志 真值为1 假值为0
OF OV NV Overflow not Overflow
SF NG PL NG = negative 负数 PL = positive 正数
ZF ZR NZ ZR = Zero NZ = not Zero
PF PE PO PE = Even 偶数 PO = odd 奇数
CF CY NC CY = Carry Yes(进位) NC= notCarry
DF DN UP DN = Down
mul、div 乘法、除法指令不影响标志位
CF 是把结果都当做无符号运算
OF 是有符号运算
adc指令 add carry
add ax,bx ax = ax + bx + carry
sbb sub carry
cmp指令
sub ax,bx ax = ax - bx
cmp ax,bx 只执行 ax-bx 这个过程,不保存结果至ax中,但是会修改标志位
je equal
jne not equal
jb below
jnb not below
ja above
jna not above
内中断
中断:发生了需要CPU立刻去处理的信息
1.除法错误 divide overflow
2.单步执行 debug
3.执行into指令
4.执行int指令
中断信息 需要一个程序去处理
CS,IP => 需要处理的程序入口 段地址,偏移地址
中断向量表 中断类型码
0号处理中断信息的程序地址 CS:IP
1号处理中断信息的程序地址 CS:IP
2号处理中断信息的程序地址 CS:IP
0000:0000 - 0000:03FF
段地址:N*4+2 偏移地址:N*4
中断过程
1.取得中断类型码
2.保存标志寄存器 => 栈 pushf
3.将标志寄存器的第8 TF 和 第9位 IF 设置为0
4.push cs
5.push ip
6.cs = N*4+2 ip = N*4
中断处理程序返回的办法
//ss:sp ip cs pushf
iret // 一条程序等于下面三条程序的效果
pop ip
pop cs
popf
int 指令
1.取中断类型码N
2.标志位寄存器入栈 IF = 0 TF = 0
3.push cs push ip
4.cs = N*4+2 ip = N*4
BIOS 和 DOS 所提供的中断的例程 = 中断程序
BIOS 系统登记在中断向量表里的
ROM内存只允许读取 不允许写入的 固化在内存中
BIOS Basic Input output System
1.硬件系统的检测和初始化程序
2.将外部中断和内部中断程序登记在 中断向量表中
3.用于对硬件设备进行 I/O 操作的中断程序 放到中断向量表中
4.其他相关于硬件系统的 中断程序
电脑开机
CS = FFFF IP = 0
1.硬件系统的检测和初始化程序
2.将中断程序的 CS 和 IP 直接登记在中断向量表中
3.调用 into9H 进行操作的系统引导,将计算机交给操作系统控制 DOS
4.DOS 系统将相应的 中断程序入口地址 存到中断向量表中 包括程序
shl 左移指令
1.将一个寄存器 或者内存单元 中的数据向左移位 bit位
2.将移除的这一位 放到 CF 中
3.最低位用 0 补充
shr 右移指令
用int 13H 中断程序,对磁盘进行读写 ;BIOS
软盘 C盘 0面0道1扇 ;start system
上下两面
一面 = 80磁道
-磁道 = 18扇区
-扇区 = 512字节
2 * 80 * 18 * 512 = 1440KB 1.44M
面号 从0开始
磁道 从0开始
扇区 从1开始