汇编语言_基础

1.基础知识(1)

 

  2.基础知识(2)

2.1由机器语言到汇编语言

2.1.1机器语言与机器指令

  • 机器语言是机器指令的集合
  • 机器语言是机器指令的集合
  • 机器指令由一串二进制数表示,例01010000

2.1.2汇编语言与汇编指令

  • 汇编语言的主体是汇编指令
  • 汇编指令和机器指令的差别在于指令的表示方法上
    • 汇编指令和机器指令的差别在于指令的表示方法上
    • 汇编指令是机器指令的助记符
  • 寄存器:CPU中可以存储数据的器件。一个CPU中有多个寄存器。
机器指令:1000100111011000
操作:将寄存器BX的内容送到AX中
汇编指令:MOV AX,BX

2.1.3用汇编语言编写程序的工作过程

2.2计算机的组成

  • 主板上有::CPU:总线:内存(条):扩展槽(接外部设备) 

2.2.1计算机的组成

  • CPU是计算机的核心部件,它控制整个计算机的运作并进行运算。要想让一个CPU工作,就必须向它提供指令和数据。
  • 指令和数据在存储器(内存)中存放。离开了内存,性能再好的CPU也无法工作。

2.2.2指令和数据的表示

  • 计算机中的数据和指令,存储在内存或磁盘上。
  • 数据和指令,都是二进制信息。
  • 问题:二进制信息1000100111011000是数据,还是指令?
    • 1000100111011000─>89D8H(数据)
    • 1000100111011000─>MOVAX,BX(程序)
  • 数据如何表示?
    • 1000100111011000B(二进制);
    • 89D8H(十六进制);
    • 104730O(八进制);
    • 35288D(十进制)
  • 数据量:B、KB、MB、GB、TB...

2.2.3计算机中的存储单元

存储器被划分为若干个存储单元,每个存储单元从0开始顺序编号

2.2.4计算机中的总线

  • 在计算机中专门有连接CPU和其他芯片的导线,通常称为总线。
  • 物理上:一根根导线的集合;逻辑上划分为.地址总线.数据总线.控制总线

2.2.5三类总线

  • CPU是通过地址总线来指定存储单元的。地址总线宽度,决定了可寻址的存储单元大小。N根地址总线(宽度为N),对应寻址空间2N。
  • CPU与内存或其它器件之间的数据传送是通过数据总线来进行的。数据总线的宽度决定CPU和外界的数据传送速度。例:向内存中写入数据89D8H时的数据传送
  • CPU通过控制总线对外部器件进行控制。控制总线是一些不同控制线的集合。控制总线宽度决定了CPU对外部器件的控制能力。

2.3内存的读写与地址空间

2.3.1CPU对存储器的读写

  • CPU要想进行数据的读写,必须和外部器件进行三类信息的交互:
    • 存储单元的地址(地址信息)
    • 器件的选择,读或写命令(控制信息)
    • 读或写的数据(数据信息)
机器码:101000000000001100000000
16进制:A00300
汇编指令:MOV AL,[3]
含义:从3号单元读取数据送入寄存器AL

2.3.2内存地址空间

  • CPU地址总线宽度为N,寻址空间为2NB;8086CPU的地址总线宽度为20,那么可以寻址1MB个内存单元,其内存地址空间为1MB
  • 从CPU角度看地址空间分配

2.3.3将各类存储器看作一个逻辑存储器——统一编址

  • 所有的物理存储器被看作一个由若干存储单元组成的逻辑存储器;
  • 每个物理存储器在这个逻辑存储器中占有一个地址段,即一段地址空间;
  • CPU在这段地址空间中读写数据,实际上就是在相对应的物理存储器中读写数据。

3.寄存器

3.1寄存器及数据存储

 3.1.1CPU的组成

  • 运算器进行信息处理;
  • 寄存器进行信息存储;
  • 控制器协调各种器件进行工作;
  • 内部总线实现CPU内各个器件之间的联系。

3.1.2寄存器是CPU内部的信息存储单元

  • 8086CPU有14个寄存器:
    • 通用寄存器:AX、BX、CX、DX;
    • 变址寄存器:SI、DI;
    • 指针寄存器:SP、BP;
    • 指令指针寄存器:IP;
    • 段寄存器:CS、SS、DS、ES;
    • 标志寄存器:PSW
  • 共性;8086CPU所有的寄存器都是16位的,可以存放两个字节。
  • 通用寄存器均可以分为两个独立的8位寄存器使用

3.1.3“字”在寄存器中的存储

  •  8086是16位CPU;8086的字长(wordsize)为16bit

  • 一个字(word)可以存在一个16位寄存器中;

    • 这个字的高位字节存在这个寄存器的高8位寄存器;

    • 这个字的低位字节存在这个寄存器的低8位寄存器

3.2mov和add指令

 注意:汇编指令不区分大小写

3.2.1汇编指令执行的结果

3.3确定物理地址的方法

 3.3.1物理地址

  • CPU访问内存单元时要给出内存单元的地址。
  • 所有的内存单元构成的存储空间是一个一维的线性空间。
  • 每一个内存单元在这个空间中都有唯一的地址,这个唯一的地址称为物理地址。
  • 事实:
    • 8086有20位地址总线,可传送20位地址,寻址能力为1M。
    • 8086是16位结构的CPU.运算器一次最多可以处理16位的数据,寄存器的最大宽度为16位。
    • 在8086内部处理的、传输、暂存的地址也是16位,寻址能力也只有64KB

3.3.28086CPU给出物理地址的方法

  • 8086CPU的解决方法:用两个16位地址(段地址、偏移地址)合成一个20位的物理地址。
  • 地址加法器合成物理地址的方法:物理地址=段地址×16+偏移地址

 3.4内存的分段表示法

3.4.1用分段的方式管理内存

  • 8086CPU用“(段地址×16)+偏移地址=物理地址”的方式给出内存单元的物理地址。
  • 内存并没有分段,段的划分来自于CPU!

3.4.2同一段内存,多种分段方案

  1. 段地址×16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;
  2. 偏移地址为16位,16位地址的寻址能力为64K,所以一个段的长度最大为64K。 

3.4.3段寄存器

  • CS-代码段寄存器
  • DS-数据段寄存器
  • SS-栈段寄存器
  • ES-附加段寄存器

3.5CS、IP与代码段

3.5.1两个关键的寄存器

  • CS:代码段寄存器
  • IP:指令指针寄存器
  • CS:IP:CPU将内存中CS:IP指向的内容当作指令执行。

3.6jmp指令

3.6.1修改CS、IP的指令

  • 事实:执行何处的指令,取决于CS:IP
  • 应用:可以通过改变CS、IP中的内容,来控制CPU要执行的目标指令
  • 问题:如何改变CS、IP的值?
    • 方法1:Debug中的R命令可以改变寄存器的值——rcs,rip;Debug是调试手段,并非程序方式!
    • 方法2:用指令修改

    • 方法3:转移指令jmp

3.6.2转移指令jmp

  • 同时修改CS、IP的内容: jmp段地址:偏移地址
    • jmp2AE3:3
    • jmp3:0B16
    • 功能:用指令中给出的段地址修改CS,偏移地址修改IP。
  • 仅修改IP的内容jmp某一合法寄存器jmpax(类似于movIP,ax)
    • jmpbx功能:用寄存器中的值修改IP。

3.7内存中字的存储

3.7.1字单元

  • 字单元:由两个地址连续的内存单元组成,存放一个字型数据(16位)
  • 原理:在一个字单元中,低地址单元存放低位字节,高地址单元存放高位字节
    • 在起始地址为0的单元中,存放的是4E20H
    • 在起始地址为2的单元中,存放的是0012H

  • 问题:
    • (1)0地址单元中存放的字节型数据是( 20H)
    • (2)0地址字单元中存放的字型数据是( 4E20H)
    • (3)2地址单元中存放的字节型数据是( 12H)
    • (4)2地址字单元中存放的字型数据是( 0012H)

3.8用DS和[address]实现字的传送

3.8.1要解决的问题:CPU从内存单元中要读取数据

  • 要求;CPU要读取一个内存单元的时候,必须先给出这个内存单元的地址;

  • 原理;在8086PC中,内存地址由段地址和偏移地址组成(段地址:偏移地址)

  • 解决方案:DS和[address]配合:

    • 用DS寄存器存放要访问的数据的段地址;

    • 偏移地址用[...]形式直接给出

3.8.2字的传送

 

 3.9DS与数据段

3.9.1对内存单元中数据的访问

  • 对于8086PC机,可以根据需要将一组内存单元定义为一个段。
    • 物理地址=段地址×16+偏移地址;
    • 将一组长度为N(N≤64K)、地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。
  • 例:用123B0H~123B9H的空间来存放数据;
    • 段地址:123BH   起始偏移地址:0000H  长度:10字节;
    • 段地址:1230H起始偏移地址:00B0H长度:10字节;
  • 处理方法:(DS):([address])
    • 用DS存放数据段的段地址;
    • 用相关指令访问数据段中的具体单元,单元地址由[address]指出

3.9.2练习

 3.9.3用mov指令操作数据

指令形式例示
mov寄存器,数据mov ax,8
mov寄存器,寄存器mov ax,bx
mov寄存器,内存单元mov ax,[0]
mov内存单元,寄存器mov[0],ax
mov段寄存器,寄存器mov ds,ax

3.9.4加法add和减法sub指令

3.10栈及栈操作的实现

 3.10.1栈结构

  • 栈是一种只能在一端进行插入或删除操作的数据结构。
  • 栈有两个基本的操作:入栈和出栈。
    • 入栈:将一个新的元素放到栈顶;
    • 出栈:从栈顶取出一个元素。
  • 栈顶的元素总是最后入栈,需要出栈时,又最先被从栈中取出。
  • 栈的操作规则:LIFO(LastInFirstOut,后进先出)
  • CPU提供的栈机制
    • 现今的CPU中都有栈的设计。
    • 8086CPU提供相关的指令,支持用栈的方式访问内存空间。
    • 基于8086CPU的编程,可以将一段内存当作栈来使用。
PUSH(入栈)和POP(出栈)指令
push  ax:将ax中的数据送入栈中
pop   ax:从栈顶取出数据送入ax(以字为单位对栈进行操作)
  • 8086CPU中,有两个与栈相关的寄存器
    • 栈段寄存器SS-存放栈顶的段地址
    • 栈顶指针寄存器SP-存放栈顶的偏移地址
  • ——任意时刻,SS:SP指向栈顶元素。

3.10.2栈的操作

 3.10.3push指令和pop指令的执行过程

 3.10.4栈的小结

  • push、pop实质上就是一种内存传送指令,可以在寄存器和内存之间传送数据,与mov指令不同的是,push和pop指令访问的内存单元的地址不是在指令中给出的,而是由SS:SP指出的。:
  • 执行push和pop指令时,SP中的内容自动改变。
  • 8086CPU提供的栈操作机制:
    • 在SS,SP中存放栈顶的段地址和偏移地址,入栈和出栈指令根据SS:SP指示的地址,按照栈的方式访问内存单元。
    • push指令的执行步骤:
      • 1)SP=SP-2;
      • 2)向SS:SP指向的字单元中送入数据。
    • pop指令的执行步骤:
      • 1)从SS:SP指向的字单元中读取数据;
      • 2)SP=SP-2

3.11段的总结

  • 基础:
    • 物理地址=段地址×16+偏移地址
  • 做法:
    • 编程时,可以根据需要将一组内存单元定义为一个段。
    • 可以将起始地址为16的倍数,长度为N(N≤64K)的一组地址连续的内存单元,定义为一个段。
    • 将一段内存定义为一个段,用一个段地址指示段,用偏移地址访问段内的单元——在程序中可以完全由程序员安排。
  • 三种段
    • 数据段.
      • 将段地址放在DS中.
      • 用mov、add、sub等访问内存单元的指令时,CPU将我们定义的数据段中的内容当作数据段来访问;
    • 代码段.
      • 将段地址放在CS中,将段中第一条指令的偏移地址放在IP中.
      • CPU将执行我们定义的代码段中的指令;
    • 栈段.
      • 将段地址放在SS中,将栈顶单元的偏移地置放在SP中.
      • CPU在需要进行栈操作(push、pop)时,就将我们定义的栈段当作栈空间来用。

4.[BX]和loop指令

4.1[...]和(...)

4.1.1[...]的规定与(...)的约定

  • [...]——(汇编语法规定)表示一个内存单元

  • (...)——(为学习方便做出的约定)表示一个内存单元或寄存器中的内容

4.1.2约定:符号idata表示常量

例:

  • mov ax,[idata]:代表movax,[1]、movax,[2]、movax,[3]...
  • mov bx,idata:代表movbx,1、movbx,2、movbx,3...
  • mov ds,idata:代表movds,1、movds,2...(都是非法指令)

4.2Loop指令

4.2.1Loop指令

  • 功能:实现循环(计数型循环)
  • 指令的格式:loop   标号
  • CPU执行loop指令时要进行的操作
    • ①(cx)=(cx)-1;
    • ②判断cx中的值不为零则转至标号处执行程序如果为零则向下执行。
  • 要求:
    • cx中要提前存放循环次数,因为(cx)影响着loop指令的执行结果;
    • 要定义一个标号

4.2.2用loop指令编程实例

  •  用cx和loop指令相配合实现循环功能的三个要点:
    • (1)在cx中存放循环次数;
    • (2)用标号指定循环开始的位置;
    • (3)在标号和loop指令的中间,写上要循环执行的程序段(循环体)。

问题:计算123x236,结果存储在ax中

方法:用加法实现乘法,将123连加236次

 4.3段前缀的使用

4.3.1段前缀的使用

  • Debug中,moval,[0]的功能是——将DS:0存储单元的值传给AL

  •  编译(masm)并连接(link)后...

  •  编译好的程序中,moval,[0]变成了将常量0传给AL

4.3.2 访问连续的内存单元——loop和[bx]联手

  • 问题:计算ffff:0~ffff:b字节单元中的数据的和,结果存储在dx中
  • 分析:
    • (1)运算后的结果是否会超出dx所能存储的范围?ffff:0~ffff:b内存单元中的数据是字节型数据,范围在0~255之间,12个这样的数据相加,结果不会大于65535,可以在dx中存放下。
    • (2)是否可以将ffff:0~ffff:b中的数据直接累加到dx中?adddx,ds:[addr];(dx)=(dx)+?期望:取出内存中的8位数据进行相加实际:取出的是内存中的16位数据
    • (3)是否可以将ffff:0~ffff:b中的数据直接累加到dl中?adddl,ds:[addr];(dl)=(dl)+?期望:取出内存中的8位数据相加实际:取出的是内存中的8位数据,但很有可能造成进位丢失。
  • 对策:取出8位数据,加到16位的寄存器
    • mov al,ds:[addr]
    • mov ah,0
    • add dx,ax

5.包含多个段的程序

5.1在代码段中使用数据

5.1.1应用案例

 5.1.2这个程序有问题

5.1.3改进 

5.2在代码段中使用栈

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

 

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

6.1处理字符问题

6.2[bx + idata]方式寻址

6.3SI和DI寄存器

 6.4 [bx+si]和[bx+di]方式寻址

6.5[bx+si+idata]和[bx+di+idata]

6.6不同的寻址方式的灵活应用

6.7用于内存寻址的寄存器

7.数据处理的两个基本问题 

7.1在哪里?有多长?

7.2寻址方式的综合应用

7.3用div指令实现除法

7.4用dup设置内存空间

 

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小鱿鱼G

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值