汇编语言学习笔记(持续更新)

原笔记,建议看这个(点我点我)

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)要处理的数据有多长?

寻址方式:

WEBRESOURCE472f771b142d3879156460624b759f1a

相关知识:

寄存器:

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

(更新中,此篇仅为了记录每日进展,待学完后将会把笔记整理好发出)

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值