汇编语言知识点整理

汇编语言

基础知识

汇编语言的产生

汇编指令和机器指令的差别在于指令的表示方式上。汇编指令是机器指令便于记忆的书写格式。

汇编语言的组成

汇编指令:机器码的助记符,有对应的机器码

伪指令:没有对应的机器码,由编译器执行,计算机并不执行

其他符号:如+、-、*、/等,由编译器识别32万

汇编指令决定了汇编语言的特性

存储器

指令和数据在存储器中存放

信息交换

存储单元的地址(地址信息)

器件的选择,读或写的命令(控制信息)

读或写的数据(数据信息)

总线

地址总线

CPU用地址总线来指定存储器单元

数据总线

CPU与内存或其他器件的数据传送是通过数据总线来进行的

数据总线的宽度决定了CPU和外界的数据传送速度

8086CPU的数据总线宽度为16

控制总线

CPU对外部器件的控制是通过控制总线来进行的

内存地址空间

和CPU的总线相连

CPU对它们进行读或写的时候都通过控制控制线发出内存读写命令

内存地址空间的大小受CPU地址总线宽度的限制

8086CPU的地址总线宽度为20,可以传送2^20个不同的地址信息

8086CPU的内存地址空间大小为1MB

原码, 反码, 补码的基础概念和计算方法

在探求为何机器要使用补码之前, 让我们先了解原码, 反码和补码的概念.对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式.

1. 原码

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:

[+1]原 = 0000 0001

[-1]原 = 1000 0001

第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:

[1111 1111 , 0111 1111]

[-127 , 127]

原码是人脑最容易理解和计算的表示方式.

2. 反码

反码的表示方法是:

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

[+1] = [00000001]原 = [00000001]反

[-1] = [10000001]原 = [11111110]反

可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算.

3. 补码

补码的表示方法是:

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

[+1] = [00000001]原 = [00000001]反 = [00000001]补

[-1] = [10000001]原 = [11111110]反 = [11111111]补

对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.

debug指令

-R 查看修改CPU寄存器内容

-D 查看内存中内容

-E 改写内存中内容

-U 将内存中的机器语言翻译成汇编指令

-T 执行一条汇编指令

-A 以汇编指令的格式在内存中写入一条机器指令

寄存器

8086CPU有14个寄存器,分别为:AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW

通用寄存器

AX,BX,CX,DX 称作为数据寄存器:

AX (Accumulator):累加寄存器,也称之为累加器;

AX可分为AH和AL

低8位构成了AL寄存器,高8位构成AH寄存器

BX (Base):基地址寄存器;

CX (Count):计数器寄存器;

DX (Data):数据寄存器;

SP 和 BP 又称作为指针寄存器:

SP (Stack Pointer):堆栈指针寄存器;

BP (Base Pointer):基指针寄存器;

SI 和 DI 又称作为变址寄存器:

SI (Source Index):源变址寄存器;

DI (Destination Index):目的变址寄存器;

控制寄存器:

IP (Instruction Pointer):指令指针寄存器;

FLAG:标志寄存器

段寄存器:

CS (Code Segment):代码段寄存器;

DS (Data Segment):数据段寄存器;

SS (Stack Segment):堆栈段寄存器;

ES (Extra Segment):附加段寄存器;

字在寄存器中的存储

字节:记为byte,一个字节由8个bit组成,可以存在8位寄存器中

字:记为word,一个字由两个字节组成,这两个字节分别被称为这个字的高位字节和低位字节

8086CPU给出物理地址的方法

8086CPU有20位地址总线,可以传送20位地址,但它只能送出16位的地址

采用两个16位地址合成的方法来形成一个20位的物理地址

当8086CPU要读写内存时

地址加法器采用物理地址=段地址*16+偏移地址

基础地址+偏移地址=物理地址

段地址*16必然是16的倍数,所以一个段的起始地址也不一定是16的倍数,16位地址的寻址能力为64KB

CPU可以用不同的段地址和偏移地址形成同一个物理地址

偏移地址16位,变化范围为0~FFFFH,仅用偏移地址来寻址最多可寻64KB个内存单元

段寄存器

8086CPU有4个段寄存器:CS,DS,SS,ES

CS为代码段寄存器

IP为指令指针寄存器

读取一条指令后,IP中的值自动增加,以使CPU可以读取下一条指令

8086CPU的工作过程

1.从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器

2.IP=IP+所读取指令的长度,从而指向下一条指令

3.执行指令。转到步骤1,重复这个过程

CPU将CS:IP指向的的内容看作指令,因为在任何时候,CPU将CS、IP中的内容当作指令的段地址和偏移地址,用它们合成指令的物理地址,到内存中读取指令码,执行。

修改CS、IP的指令

8086CPU为CS、IP提供了另外的指令来改变它们的值。能够改变CS、IP的内容的指令被统称为转移指令

jmp指令

jmp段地址:偏移地址

功能:用指令中给出的段地址修改CS,偏移地址修改IP

若想仅修改IP的内容,可用形如“jmp 某一合法寄存器”的指令完成

功能:用寄存器中的值修改IP

寄存器(内存访问)

内存中字的存储

CPU中用16位寄存器来存储一个字。高八位存放高位字节,第八位存放低位字节。

字单元

即存放一个字型数据(16位)的内存单元,有两个地址连续的内存单元组成。高地址内存单元中存放字型数据的高位字节,低地址内存单元中存放字型数据的低位字节

任何两个地址连续的内存单元,N号单元和N+1号单元,可以把它们看成两个内存单元,也可以看成一个地址为N的字单元中的高位字节单元和低位字节单元

DS和[address]

DS 寄存器通常用来存放要来访问的数据的段地址

“[…]”表示一个内存单元

“[0]”中的0表示内存单元的偏移地址

8086CPU自动取ds中的数据为内存单元的段地址

8086CPU不支持将数据直接送入段寄存器的操作,只好用一个寄存器来进行中转,即先将1000H送入一个一般的寄存器,如bx,再将bx 中的内容送入ds

mov ax,[0]l;1000:0处的字型数据送入ax
mov [0],cx;cx中的16位数据送到1000:0处

栈是一种具有特殊的访问方式的存储空间。它的特殊性就在于,最后进入这个空间的数据,最先出去

出栈入栈指令

PUSH入栈

执行步骤:1.sp=sp-2;2.向SS;SP指向的字单元中送入数据

POP出栈

执行步骤:1.从SS:SP指向的字单元中读取数据;2.sp=sp+2

出栈和入栈操作都是以字为单位进行的

段寄存器SS和寄存器SP,栈顶的段地址存放在SS中,偏移地址存放在SP中。任意时刻,SS:SP指向栈顶元素,CPU从SS和SP中得到栈顶的地址

入栈时,栈顶从高地址向低地址方向增长

栈空的时候 SP=0010H

注意

8086CPU不保证我们对栈的操作不会超界。它只会考虑当前的情况:当前的栈顶在何处、当前要执行的指令是哪一条

栈段

栈空时:SP=0000H

第一个程序

一个源程序从写出到执行的过程

1.编写汇编源程序

2.对源程序进行编译连接

3.执行可执行执行文件中的程序

伪指令

汇编指令是有对应的机器码的指令,可以被编译为机器语言,最终为CPU所执行。伪指令没有对应的机器指令,最终不被CPU所执行。伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作。

segment和ends

segment和ends的功能是定义一个段

段名 segment
.
.
.
段名 ends

end

end是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令end,就结束对源程序的编译

assume

assume的含义为假设。它假设某一段寄存器和程序中的某一个用segment…ends定义的段相关联

assume cs:codesg
将段codesg和CPU中的段寄存器CS联系起来

程序返回

mov ax,4c00H
int 21H

编译和连接

masm进行编译

link进行连接

用Debug来跟踪一个程序的运行过程

[BX]和loop指令

内存单元

1.内存单元的地址

2.内存单元的长度

[bx]

[bx]同样也表示一个内存单元,它的偏移地址在bx中

mov ax,[bx]将一个内存单元的内容送入ax,这个内存单元的长度为2字节,存放一个字,偏移地址在bx中,段地址在ds中
mov al,[bx]将一个内存单元的内容送入al,这个内存单元的长度为1字节,存放一个字,偏移地址在bx中,段地址在ds中

Inc bx的含义是bx 中的内容加1

loop

格式为:loop 标号

CPU 执行loop指令的时候,要进行两步操作

1.(cx)=(cx)-1

2.判断cx中的值,不为零择转至标号处执行程序,如果为零则向下执行

我们用loop指令来实现循环功能,cx中存放循环次数

描述性的符号:“()”

用“()”来表示一个寄存器或一个内存单元中的内容

在汇编源程序中,数据不能以字母开头,所以要在前面加0

在汇编源程序中,如果用指令访问一个内存单元,则在指令中必须用“[…]”来表示内存单元,如果在“[]”里用一个常量idata直接给出内存单元的偏移地址,就要在“[]”的前面显式地给出段地址所在的段寄存器

mov al,ds:[0]

如果没有在“[]”前面显式地给出段地址所在的段寄存器

mov al,[0]

那么,编译器masm将把指令中的“[idata]”解释为“idata”

如何将ffff:0~ffff:b中的8位数据,累加到16位寄存器dx中

1.(dx)=(dx)+内存中的8位数据

2.(dl)=(dl)+内存中的8位数据

段前缀

出现在访问内存单元的指令中,用于显式地说明内存单元的段地址的“ds:”“cs:”“ss:”“es:”

安全空间

0:200~0:2ff

包含多个段的程序

在代码段中使用数据

dw

含义是定义字形数据

dw 0123h,0456h,0789h,0abch,0defh,0fedh,0cbah,0987h

这里使用dw定义了8个字型数据

它们在代码段中,程序在运行的时候CS中存放代码段的段地址,所以可以从CS中得到它们的段地址。它们的的偏移地址,由于在代码段的最开始,所以开始为0,所以依次为CS:0、CS:2、CS:4、CS:6、CS:8、CS:A、CS:C、CS:E

可执行文件中的程序执行过程

1.由其他的程序将可执行文件中的程序加载入内存

2.设置CS:IP指向程序的第一条要执行的指令,从而使程序得以运行

3.程序运行结束后,返回到加载者

框架
assume cs:code
code segment
.
.
数据
.
.
start:
.
.
代码
.
.
code ends 
end start+

在代码中使用栈

将数据、代码、栈放入不同的段

更灵活的定位内存地址的方法

and指令

and指令:逻辑与指令,按位进行与运算

只有1和1为1

mov al,01100011B
and al,00111011B
执行后:al=00100011B

or 指令

or指令:逻辑或指令,按位进行或运算

只有0和0为0

mov al,01100011B
and al,00111011B
执行后:al=01111011B

ASCII编码

以字符形式给出的数据

db:定义二进制数

大小写转换

大写字母+20H=小学字母

s:mov al,[bx]
 and al ,11011111B

将al中的ASCII码的第5位置为0,变为大写字母

小写字母-20H=大写字母

s:mov al,[bx]
 or al ,00100000B

将al中的ASCII码的第5位置为1,变为小写字母

[bx+idata]

数据处理的两个基本问题

bx、si、di、bp

只有这四个寄存器可以用在“[…]”中来进行内存单元的寻址

在[…]中这4个寄存器可以单独出现或者组合出现

在[…]中使用寄存器bp,而指令中没有显性地给出段地址,段地址默认在ss中

机器指令处理的数据在什么地方

指令执行前一刻 ,它将要处理的数据所在的位置

内存单元

CPU内部,寄存器

CPU内部,指令缓存器

汇编语言中数据位置的表达

立即数

直接包含在机器指令中的数据(执行前在CPU的指令缓存器中)

寄存器

指令要处理的数据在寄存器中

段地址和偏移地址

指令要处理的数据在内存中

寻址方式

直接寻址
寄存器间接寻址
寄存器相对寻址
基址变址寻址
相对基址变址寻址

指令要处理的数据有多长

通过寄存器名指明要处理的数据的尺寸
用操作符 word ptr,byte ptr来指明内存单元的长度
有些指令默认了访问的单元大小

div指令

div是除法指令

除数:有8位和16位

被除数:放在AX或DX和AX中

结果:如果除数为8位,则AL中存放除法操作的商,AH存储除法操作的余数;如果除数为16位,则AX中存放除法操作的商,DX存储除法操作的余数

当除数是8位的时候,被除数为16位,放在AX中存放,AL中存放除法操作的商,AH存储除法操作的余数

当除数是16位的时候,被除数为32位,放在DX和AX中存放,AX中存放除法操作的商,DX存储除法操作的余数

伪指令dd

dd是用来定义字节型数据的

db是用来定义字型数据的

dw是用来定义dword型数据的

dup

db 重复的次数 dup(重复的字节型数据)

dw 重复的次数 dup(重复的字型数据)

dd 重复的次数 dup(重复的双字型数据)

转移指令的原理

可以修改IP,或同时修改CS和IP的指令统称为转移指令

段内转移:只修改IP

段间转移:同时修改CS和IP

段内转移又分为短转移和近转移

短转移IP的修改范围为-128~127

近转移IP的修改范围为-32768~32767

offset

功能是取得标号的偏移地址

jmp指令

jmp为无条件转移指令

jmp要给出两种信息:

1.转移的目的地址

2.转移的距离(段间转移、段内短转移、段内近转移)

根据位移进行转移的jmp指令

jmp short 标号

段内短转移

CPU在执行jmp指令的时候并不需要转移的目的地址

转移的目的地址在指令中的jmp指令

jmp far ptr 标号

段间转移,远转移

转移地址在寄存器中的jmp指令
转移地址在内存中的jmp指令

jmp word ptr 内存单元地址(段内转移)

jmp dword ptr 内存单元地址(段间转移)

jcxz指令

为有条件转移指令

loop指令

循环指令

短转移

CALL和RET指令

ret

用栈中的数据,修改IP的内容,从而实现近转移

retf

用栈中的数据,修改CS和IP的内容,从而实现远转移

call

两步操作

1.将当前的IP或CS和IP压入栈内

2.转移

依据位移进行转移的call指令

call标号(将当前的IP压栈后,转到标号处执行指令)

转移的目的地址在指令中的call指令

call far ptr 标号

实现段间转移

转移地址在寄存器中的call指令

call 16位reg

转移地址在内存中的call指令

call word ptr 内存单元地址

call dword ptr 内存单元地址

call和ret的配合使用

可以利用call和ret来实现子程序的机制

框架

assume cs:code
code segment
  main:
       .
       .
       call sub1             ;调用子程序sub1
       .
       .
       mov ax ,4c00h
       int 21h
  sub1:                      ;子程序sub1开始
       .
       .
       call sub2             ;调用子程序sub2
       .
       .
       ret                   ;子程序返回
  sub2:                      ;子程序sub2开始
       .
       .
       ret                   ;子程序返回
code ends
end main

mull指令

mull是乘法指令

两个相乘的数要么都是8位,要么都是16位。

当8位的时候,一个默认放在AL中,另一个放在8位reg或内存字节单元中,结果默认放AX中

当16位的时候,一个默认放在AX中,另一个放在16位reg或内存字节单元中,结果高位默认放DX中,低位在AX中放

汇编语言(各章知识点) 课程介绍 第1章 预备知识  1.1 汇编语言的由来及其特点   1 机器语言   2 汇编语言   3 汇编程序   4 汇编语言的主要特点   5 汇编语言的使用领域  1.2 数据的表示和类型   1 数值数据的表示   2 非数值数据的表示   3 基本的数据类型  1.3 习题 第2章 CPU资源和存储器  2.1 寄存器组   1 寄存器组   2 通用寄存器的作用   3 专用寄存器的作用  2.2 存储器的管理模式   1 16位微机的内存管理模式   2 32位微机的内存管理模式  2.3 习题 第3章 操作数的寻址方式  3.1 立即寻址方式  3.2 寄存器寻址方式  3.3 直接寻址方式  3.4 寄存器间接寻址方式  3.5 寄存器相对寻址方式  3.6 基址加变址寻址方式  3.7 相对基址加变址寻址方式  3.8 32位地址的寻址方式  3.9 操作数寻址方式的小结  3.10 习题 第4章 标识符和表达式  4.1 标识符  4.2 简单内存变量的定义   1 内存变量定义的一般形式   2 字节变量   3 字变量   4 双字变量   5 六字节变量   6 八字节变量   7 十字节变量  4.3 调整偏移量伪指令   1 偶对齐伪指令   2 对齐伪指令   3 调整偏移量伪指令   4 偏移量计数器的值  4.4 复合内存变量的定义   1 重复说明符   2 结构类型的定义   3 联合类型的定义   4 记录类型的定义   5 数据类型的自定义  4.5 标号  4.6 内存变量和标号的属性   1 段属性操作符   2 偏移量属性操作符   3 类型属性操作符   4 长度属性操作符   5 容量属性操作符   6 强制属性操作符   7 存储单元别名操作符  4.7 表达式   1 进制伪指令   2 数值表达式   3 地址表达式  4.8 符号定义语句   1 等价语句   2 等号语句   3 符号名定义语句  4.9 习题 第5章 微机CPU的指令系统  5.1 汇编语言指令格式   1 指令格式   2 了解指令的几个方面  5.2 指令系统   1 数据传送指令   2 标志位操作指令   3 算术运算指令   4 逻辑运算指令   5 移位操作指令   6 位操作指令   7 比较运算指令   8 循环指令   9 转移指令   10 条件设置字节指令   11 字符串操作指令   12 ASCII-BCD码调整指令   13 处理器指令  5.3 习题 第6章 程序的基本结构  6.1 程序的基本组成   1 段的定义   2 段寄存器的说明语句   3 堆栈段的说明   4 源程序的结构  6.2 程序的基本结构   1 顺序结构   2 分支结构   3 循环结构  6.3 段的基本属性   1 对齐类型   2 组合类型   3 类别   4 段组  6.4 简化的段定义   1 存储模型说明伪指令   2 简化段定义伪指令   3 简化段段名的引用  6.5 源程序的辅助说明伪指令   1 模块名定义伪指令   2 页面定义伪指令   3 标题定义伪指令   4 子标题定义伪指令  6.6 习题 第7章 子程序和库  7.1 子程序的定义  7.2 子程序的调用和返回指令   1 调用指令   2 返回指令  7.3 子程序的参数传递   1 寄存器传递参数   2 存储单元传递参数   3 堆栈传递参数  7.4 寄存器的保护与恢复  7.5 子程序的完全定义   1 子程序完全定义格式   2 子程序的位距   3 子程序的语言类型   4 子程序的可见性   5 子程序的起始和结束操作   6 寄存器的保护和恢复   7 子程序的参数传递   8 子程序的原型说明   9 子程序的调用伪指令   10 局部变量的定义  7.6 子程序库   1 建立库文件命令   2 建立库文件举例   3 库文件的应用   4 库文件的好处  7.7 习题 第8章 输入输出和中断  8.1 输入输出的基本概念   1 I/O端口地址   2 I/O指令  8.2 中断   1 中断的基本概念   2 中断指令   3 中断返回指令   4 中断和子程序  8.3 中断的分类   1 键盘输入的中断功能   2 屏幕显示的中断功能   3 打印输出的中断功能   4 串行通信口的中断功能   5 鼠标的中断功能   6 目录和文件的中断功能   7 内存管理的中断功能   8 读取和设置中断向量  8.4 习题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值