8.28
基础知识:
每种CPU有自己的指令集
十六进制后加H,十进制什么都不加,二进制加B
写汇编指令及寄存器名称时不分大小写
各类存储器在CPU中整合为一个内存地址空间
1byte=8bit
总线宽度=导线根数,每根导线有高低电平两种状态
CPU控制设备:CPU->接口卡->硬件设备
RAM:随机存储器,必须带电存储
ROM:只读存储器,断电内容不丢失
BIOS:Basic Input/Output System 基本输入/输出系统,最底层的软件程序,固化在ROM,为计算机提供最底层的、最直接的硬件设置和控制。且在主板和某些接口卡上插有存储相应BIOS的ROM。如网卡显卡
段地址:偏移地址
寄存器:
相关知识:
8086寄存器:
AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW 共十四个
其中
AX,BX,CX,DX为通用寄存器
CS(代码段),DS(数据段),SS(堆栈段),ES(附加段)为段寄存器
IP 为指令指针寄存器,CS:IP 指向CPU将要执行的指令
8086的所有寄存器为十六位,其中AX,BX,CX,DX,可分为AH,AL等共八个八位寄存器使用
寄存器间运算时位数应当一致
段的划分仅来自CPU
CS:IP的值不能通过mov指令修改,可通过jmp修改
相关指令:
mov 寄存器1,寄存器2/数值(十进制)
-----将寄存器2存储的值或该数值赋给寄存器1
add 寄存器1,寄存器2/数值(十进制)
-----将寄存器2存储的值或该数值与寄存器1的值相加,结果存入寄存器1
sub 寄存器1,寄存器2/数值(十进制)
-----寄存器1的值减去寄存器2存储的值或该数值,结果存入寄存器1
jmp 寄存器1
-----将寄存器1的值付给寄存器IP
jmp 段地址:偏移地址
-----将输入的值赋给CS:IP
DEBUG:
用R命令查看、改变CPU寄存器的内容
只按R键
-----查看各个寄存器内容
R 寄存器名
-----输入数据赋给指定寄存器,按回车确定赋值
用D命令查看内存中的内容
只按D键
-----列出预设地址内存处的128个字节的内容,继续按D则继续列出后续内容
D 段地址:偏移地址
-----列出内存中指定地址处的内容
D 段地址:偏移地址 结尾偏移地址
-----列出内存中指定地址范围内的内容
用E命令改变内存中的内容
E 段地址:偏移地址 数据1 数据2 ...
-----修改从指定地址开始的若干个数据
E 段地址:偏移地址
-----逐个询问式修改
空格 - 修改,继续
回车 - 结束
用U命令将内存中的机器指令翻译成汇编指令
u 段地址:偏移地址
-----查看指定地址机器指令对应的代码
u 段地址:偏移地址 结尾偏移地址
-----查看从指定地址到结束地址机器指令对应的代码
用A命令以汇编指令的格式在内存中写入机器指令
a 段地址:偏移地址
-----向指定地址写入汇编指令,按回车结束写入
用T命令执行机器指令
按t键
-----执行一次CS:IP处的指令
用Q命令退出Debug
按q键
-----退出Debug
寄存器(内存访问)
一个字单元用两个内存单元来储存,数据高位存在高地址处,低位存在低地址处
起始地址为N的字单元简称为N地址字单元
DS(数据段寄存器)和[address]
可直接将内存单元中的内容用来运算,
eg: mov ax [k] 则将 DS:k 处的内容拿来运算,可以做被赋值对象等其它一系列运算对象
8086CPU不支持直接给段寄存器赋值,但可以先将数据存入通用寄存器,再使用通用寄存器给段寄存器赋值
8.29
栈:
LIFO(last in first out)
8086中,SS寄存器存放栈顶的段地址,SP寄存器存放栈的偏移地址,SS:SP指向栈顶元素
指令:
PUSH 寄存器
-----先令SP=SP-2,再将寄存器内容压入SS:SP指向单元处,此时SS:SP指向栈顶
POP 寄存器
-----先将栈顶内容送入指定寄存器,再令SP=SP+2
8006中的PUSH和POP以字为单位(即16位)
栈顶由高地址向低地址增长,当栈为空时SS:SP指向栈空间最高地址的下一个单元
中断机制.....
8.30
第一个程序:
相关知识:
源程序从写出到执行的过程:
编写汇编源程序->对源程序进行编译链接->执行可执行文件中的程序
可执行文件包括两部分:程序及其数据,相关描述信息
源程序包括两种指令:
汇编指令(编译器编译为机器指令然后被CPU执行)
伪指令:(编译器执行)
相关伪指令:
segment和ends
-----配对使用,用来定义一个段,使用格式:段名 segment ........段名 ends
end
-----用来标记整个程序的结束,告诉编译器程序结束
assume
-----用来关联段寄存器与定义的某一个段(类型要对应),使用格式:assume 段寄存器:段名
标号:即前面说的段名,用来指代一个地址
源程序中最终被计算机执行处理的部分称为源程序中的“程序”
程序返回:
mov ax,4c00H int 21H,目前只知道这两条指令代表程序返回
shell:操作系统的外壳,8086中为command
debug默认所有数据都使用十六进制
生成及执行过程:
编程(Edit) --> 1.asm --> 编译(Masm) --> 1.obj --> 连接(Link) --> 1.exe --> 加载(command) --> 内存中的程序 --> 运行(CPU)
编辑源程序:
工具:Edit,编辑文本
编译:
工具:Masm,将源程序编译为obj格式文件,可生产列表文件和交叉引用文件(编译过程中的信息)
连接:
工具:Link,将obj文件处理后成为exe文件,可生成映像文件,要选择所要用到的库文件名称,Link可用来连接多个源程序或连接库文件与源程序,Link不仅连接,还会处理程序中的内容,所以哪怕是只有一个源文件且不调用库中的子程序的情况,也要使用Link处理
加载:
通过command(8086中的shell)来将该程序载入内存
程序执行过程的跟踪:
DEBUG 程序名
用t命令单步执行程序中的每一条命令,int 21 指令需要使用P命令
则由debug将程序载入内存,程序运行结束时返回debug
程序在内存中的加载过程:
找到一段起始地址为SA:0的空闲内存区,在这段空闲区的前256字节创建一个被称为PSP(程序段前缀)的数据区,DOS将通过PSP与被加载的程序通信,从 SA+10H:0 开始为程序区,将该内存区的段地址存入DS,初始化其它寄存器后,设置 CS:IP 指向程序入口
8.31
[BX]和loop指令:
相关知识:
在汇编源程序中,数据不能以字母开头
寄存器bx可作为偏移地址[bx]与段寄存器ds结合使用
王爽老师在《汇编语言》这本书中的定义:
1.(寄存器/地址单元)相当于取其中内容,即()相当于C语言中的取内容运算符 * (自己的一些理解,不对请师傅们指正)
2.idata代表常量
inc 寄存器
-----使寄存器中的内容自增一,相当于C语言中的++
debug:
用G使程序运行至IP为指定值
g 数值
-----使程序运行至IP为指定值
在执行loop时使用p指令将一次性将循环执行完
debug和masm对指令的不同处理:
在debug中 [k] 被当做 ds:k 来使用,但在masm编译过程中,[k] 将被当做数值 k 使用
可在汇编源程序中使用 ds:[k] 来达到debug中 [k] 的效果
在 [bx] 的用法上debug和masm一样
段前缀:
-----即 段寄存器: 例如“ds:” "cs:" "ss:" "es:"
一段安全的空间:随意向一段内存中写入内容是很危险的,因为不知道这段内存中存放的数据是否重要,dos和其他合法程序一般不会使用0:200-0:2ff(00200h~002ffh)的256字节空间,所以我们使用这段空间是安全的
loop指令:
使用格式:
loop 标号
-----这里的标号相当于地址
loop 数值 (有限制,但具体怎么限制不清楚)(可这样使用,但具体原理尚不清楚)
-----相当于将IP赋值为该数值
使用方法:
cx寄存器中存放循环次数
loop指令中的标号所标识的地址要放在loop前面
执行原理:
loop指令的执行分为两个步骤:
1.cx自减一
2.判断cx中的值,不为0则转到标号s所标识的地址处执行,如果为0则执行下一行指令
loop和[bx]的联合应用及段前缀的使用
记住使用方法,灵活配合调用即可,没什么需要记录的。
9.1
包含多个段的程序:(本章内容较少)
相关知识:
程序获取内存空间的途径:加载时的分配所得和运行时申请获得
指令:
dw(define word) 数值
-----定义字型数据,系统将为这些数据给其对应的段分配内存
end还可以通知编译器程序的入口在哪;
用法:
在源程序中的一行代码前添加标号:,并在结尾的end后加空格标号,则编译器将会把这一行代码当做程序入口
定义多个段的方法:段名不同即可
在程序中,段名就相当于一个标号,它代表了段地址,一个段中数据的段地址可由段名代表
9.2
更灵活的定位内存地址的方法:
相关知识:
指令:
and 寄存器/数值
-----使寄存器中的数值与该数值的每一位相比较,做与运算,有假则假,同真才真,可用来将数值的某一位(二进制)置为0
or 寄存器/数值
-----使寄存器中的数值与该数值的每一位相比较,做或运算,有真则真,同假才假,可用来将数值的某一位(二进制)置为1
ASCII码值:A- 41H a- 61H
字母大小写的转换:ASCII编码中,字母大小写状态对应的二进制数值只有第五位不同(位数从0开始,即第0位,第1位,第2位.....)
寄存器 SI 和 DI 和 bx 的功能相近,寄存器中的内容皆可作为 ds 的偏移地址以 [bx],[si],[di] 的方式来使用,但不能分为两个八位寄存器来使用。
一般来说,在需要暂存数据时,使用栈来储存。
寻址方式的灵活运用:
[bx+idata] idata[bx]
-----两种表达方式一样,皆为在bx内的数值上加idata,作为ds的偏移地址使用
[bx+si] [bx][si] (此处以寄存器 si 为例,寄存器 di 等效)
-----两种表达方式一样,意为将bx内的数值与si/di内的数值相加,作为ds的偏移地址使用
[bx+si+idata] [bx].idata[si] [bx][si].idata (此处以寄存器 si 为例,寄存器 di 等效)
-----三种表达方式一样,三者相加作为ds的偏移地址使用
9.3
数据处理的两个基本问题:
(1)处理的数据在什么地方?
(2)要处理的数据有多长?
寻址方式:
相关知识:
寄存器:
bx,si,di,bp 8086中只有这四个寄存器能在 [...] 中进行内存单元的寻址
单个使用时,[bx],[si],[di] 都以 ds 为段寄存器,但 [bp] 以 ss 为段寄存器
组合:仅 bx和si,bx和di,bp和si,bp和di 四种组合(idata可有可无),当存在 bp 时,默认以 ss 为段寄存器
三个表达数据的概念:立即数(idata) 寄存器 段地址(SA)和偏移地址(EA)
指令:
操作指令 word/byte ptr 操作对象
-----当没有寄存器名给出操作数据长度时,使用该指令给定数据长度
div 除数
-----当除数为八位时,被除数为十六位,放在 ax 中,运算结果商放在 al 中,余数放在 ah 中
当除数为十六位时,被除数为三十二位,高十六位在 dx 中,低十六位在 ax 中,运算结果商放在 ax 中,余数放在 dx 中
push 指令只进行字操作
伪指令db,dw,dd:用来定义一个 byte/word/double word 型数据
伪指令dup:与db,dw,dd配合使用,进行数据的重复
格式:
db 重复的次数 dup(重复的数据)
db 3 dup(0)即定义了三个字节,它们的值都为0
db 3 dup(0,1,2)定义了九个字节,它们的值为0,1,2,0,1,2,0,1,2,
db 3 dup(‘abc’,‘ABC')定义了十八个字节,它们是’abcABCabcABCabcABC'
9.4
转移指令的原理:
可以修改IP,或同时修改CS和IP的指令统称为转移指令
转移指令分类:无条件转移指令、条件转移指令、循环指令、过程、中断
段内转移:只修改IP
段间转移:同时修改CS和IP
短转移:修改IP范围-128~127
近转移:修改IP范围-32768~32767
offset 标号(伪指令)
-----取得标号的偏移地址,可与其它指令结合使用
nop:?????
CPU在执行jmp时不需要转移的目的地址,而是以算出的要转移的位移为准
jmp short 标号
-----段内短转移,令(IP)=(IP)+8位位移,该8位位移=标号处地址-jmp指令后的第一个字节的地址
jmp near ptr 标号
-----段内近转移,令(IP)=(IP)+16位位移,该16位位移=标号处地址-jmp指令后的第一个字节的地址
jmp far ptr 标号
-----段间转移,又称远转移,同时修改CS和IP为标号的段地址和偏移地址
jmp word ptr 内存单元地址
-----段内转移,令(IP)=(内存单元地址)
jmp dword ptr 内存单元地址
-----段间转移,令(IP)=(内存单元地址),(CS)=(内存单元地址+2)
jcxz 标号
-----判断cx是否为0,是则jmp至标号处,不是则执行下一条指令
今天时间没规划好,计划内容没学完,应当反思,加以改进
9.5
CALL和RET指令:
RET(近转移)
(1) (IP)=((ss)*16+(sp))
(2) (sp)=(sp)+2
相当于
POP IP
RETF(远转移)
(1) (IP)=((ss)*16+(sp))
(2) (sp)=(sp)+2
(3) (CS)=((ss)*16+(sp))
(4) (sp)=(sp)+2
相当于
POP IP
POP CS
CALL指令
call 标号(段内转移)
(1) (sp)=(sp)-2
((ss)*16+(sp))=(IP)
(2) (IP)=(IP)+16位位移
相当于
PUSH IP
jmp near ptr 标号
call far ptr 标号(段间转移)
(1) (sp)=(sp)-2
((ss)*16+(sp))=(CS)
(sp)=(sp)-2
((ss)*16+(sp))=(IP)
(2) (CS)=标号所在段的段地址
(IP)=标号在段中的偏移地址
相当于
PUSH CS
PUSH IP
jmp far ptr 标号
call 16位reg
(sp)=(sp)-2
((ss)*16+(sp))=(IP)
(IP)=(16位reg)
相当于
PUSH IP
jmp 16位reg
call word ptr 内存单元地址
相当于
PUSH IP
jmp word ptr 内存单元地址
call dword ptr 内存单元地址
相当于
PUSH CS
PUSH IP
jmp dword ptr 内存单元地址
call 和 ret 的配合使用自行理解,没什么好记的
今天又是没完成任务的一天,踏马的
9.6
做了第十章后面的实验和课设,有点费时间,妹继续火花往下学了
9.7
今儿写实验没学汇编,emmm
(更新中,此篇仅为了记录每日进展,待学完后将会把笔记整理好发出)