当前位置: 首页 > news >正文

汇编语言入门(二)

汇编语言入门(一)

文章目录

  • 寄存器【内存访问】
    • 内存中字的存储
    • DS和【address】
    • 字的传送
    • mov、add、sub指令
    • 数据段
    • 栈顶越界的问题
    • PUSH和POP指令
    • 栈的综述
    • 栈段【栈的综述】

寄存器【内存访问】

内存中字的存储

在这里插入图片描述
4E20是两个字节构成一个字。

上图中0地址单元中存放的字节型数据是20
0地址字节单元中存放的字型数据是4E20
2地址字单元中存放的字节型数据是12
2地址单元中存放的字型数据是0012
1地址单元中存放的字型数据是124EH

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

DS和【address】

  • CPU要读取一个内存单元的时候,必须先要给出这个内存单元的地址。
  • 8086CPU中,内存地址是由段地址和偏移地址组成。
  • 8086CPU中有一个DS寄存器,通常用来存放要访问的数据的段地址。
  • 8086CPU有4个段寄存器:CS【代码地址】、DS【数据地址】、SS【堆栈地址】、ES 【前面不够放这个寄存器】。
  • 下面三条指令将10000H【1000:0】中的数据读到AL中。
mov bx,1000H
mov ds,bx
mov al,[0]  //偏移地址为0的内存单元送入寄存器
  • 已知的mov指令可完成两种传送功能:(1)将数据直接送入寄存器;(2)将一个寄存器中的内容送入另一个寄存器中;(3)将一个内存单元中的内容送入一个寄存器。
  • 从哪个内存单元到哪个寄存器?
    mov指令的格式:mov 寄存器名,内存单元地址
  • 执行指令时,8086CPU自动取DS中的数据为内存单元的段地址。
  • CS:IP读取到的东西会被CPU认为是指令,而DS读取到的东西会直接被CPU认为是数据。
  • CSDS都是段寄存器,一个程序往往被分为好几个段,DS保存的是数据段的基地址,而CS保存的是代码段的基地址,IP中保存的是要执行的下一条指令的地址。
  • 如何用mov指令从10000H中读取数据?
  1. 10000H表示从1000:0【段地址:偏移地址】
  2. 将段地址1000H放入DS
  3. mov al,[0]完成传送【mov指令中的[]说明操作对象是一个内存单元,[]中的0说明这个内存单元的偏移地址是0,它的段地址默认放在DS中。】
  • 8086CPU不支持将数据直接送入段寄存器的操作,如mov ax,1可以,但是mov ds,1000H不可以。
  • 数据 -> 通用寄存器 -> 段寄存器
  • 如何将数据从寄存器送入内存单元?将al中的数据如何送入到内存单元10000H中?
mov bx,1000H
mov ds,bx    //前两句是确认数据的段地址
mov [0],al //这里的al是题目的要求

字的传送

  1. 因为8086CPU16位结构,有16根数据线,所以可以一次性传输16位的数据,也就是一个字。
mov bx,1000H
mov ds,bx    //前两句是确认数据的段地址
mov ax,[0]   //1000:0处的字型数据放入ax中
mov [0],cx      //cx中的16位数据送到1000:0

mov、add、sub指令

  1. mov指令的几种形式

mov 寄存器,数据
mov 寄存器,寄存器
mov 寄存器,内存单元
mov 内存单元,寄存器
mov 段寄存器,寄存器
mov 寄存器,段寄存器

  1. addsub指令同mov一样,都有两个操作对象。

在这里插入图片描述
3. sub:左边=左边-右边

数据段

  • 我们可以将一组长度为N【N<=64K】,地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。
  • 比如,我们用123B0H~123B9H这段空间来存放数据,段地址:123BH,长度:10字节。
  • 如何访问数据段中的数据呢? 将一段内存中当作数据段,是我们在编程时的一种安排,我们可以在具体操作的时候,用DS存放数据段的段地址,再根据需要,用相关指令访问数据段中的具体单元。
    在这里插入图片描述

  1. 栈是一种具有特殊的访问方式的存储空间。它的特殊性在于,最后进入这个空间的数据,最先出去。【LIFO
  2. 栈的基本操作:入栈、出栈。
  3. 现今的CPU中都有栈的设计。
  4. 8086CPU提供相关的指令以栈的方式访问内存空间,这意味着,我们在基于8086CPU编程的时候,可以将一段内存当作栈来使用。
  5. 入栈:PUSH,出栈:POP
push ax  //将寄存器ax中的数据送入栈中
pop ax  //从栈顶取出数据送入ax
  1. 8086CPU的入栈和出栈操作都是以字为单位进行的。
  2. 寄存器CSIP中存放着当前指令的段地址和偏移地址。
  3. 8086CPU中,段寄存器SS:存放栈顶的段地址,寄存器SP:存放栈顶的偏移地址。
  4. 任意时刻,SS:SP指向栈顶元素。当栈为空的时候,栈中没有元素,也就不存在栈顶元素。
  5. 所以,SS:SP只能指向栈的最底部单元下面的单元,该单元的偏移地址为栈最底部的字单元的偏移地址+2。
    在这里插入图片描述
    在这里插入图片描述

栈顶越界的问题

  • 8086CPU在工作过程中只考虑当前的情况:当前栈在何处?当前要执行的指令是哪一条。
  • 如何保证入栈、出栈时栈顶不会超出栈空间? 我们在编程的时候要自己操心栈顶超界的问题,要根据可能用到的最大栈空间来安排栈的大小,防止入栈的数据太多而导致的超界。执行出栈操作的时候也要注意。

PUSH和POP指令

  1. push和pop指令是可以在寄存器和内存之间传送数据的。

push寄存器:将一个寄存器中的数据入栈
pop寄存器:用一个寄存器接受出栈的数据。

push段寄存器:将一个段寄存器中的数据入栈
pop段寄存器:用一个段寄存器接受出栈的数据

push内存单元:将一个内存单元处的字入栈
pop内存单元:出栈,用一个内存字单元接收出栈的数据

push[0]

指令执行时,CPU要知道内存单元的地址,可以在pushpop指令中给出内存单元的偏移地址,段地址在指令执行时,CPU从DS中取得。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

mov ax,1000H
mov ss,ax
mov sp,0010H
mov ax,001AH
mov bx,001BH
push ax
push bx
sub ax,ax   // mov ax,0
sub bx,bx   // mov bx,0
pop bx
pop bx

在这里插入图片描述

mov ax,1000H
mov ss,ax
mov sp,001H
mov ax,002AH
mov bx,002BH
push ax
push bx
pop ax    //用寄存器ax接受出来的bx的数据,即可实现交换
pop bx

在这里插入图片描述
另一种写法:

mov ax,1000H
mov ss,ax
mov sp,2    
mov ax,2266H
push ax     //会执行 sp = sp -2

栈的综述

  • 栈空间当然也是内存空间的一部分,它只是一段可以以一种特殊的方式进行访问的内存空间。
  • push指令的执行步骤:
  1. sp = sp - 2
  2. 向SS:SP指向的字单元中送入数据
  • pop指令执行步骤:
  1. 从SS:SP指向的字单元中读取数据;
  2. sp = sp + 2
  • 8086CPU只记录栈顶,栈空间的大小我们要自己管理。
  • 可以用栈来暂存以后需要恢复的寄存器的内容。

栈段【栈的综述】

  1. 对于8086PC机,在编程时,我们可以根据需要,将一组内存单元定义为一个段。
  2. 我们可以将长度为NN<= 64K】的一组地址连续,起始地址为16的倍数的内存单元,当作栈来用,从而定义了一个栈段。
  3. 将一段内存当作栈段,仅仅是在编程时的一种安排,CPU不会由于这种安排,就在执行pushpop等栈操作指令时就自动将我们定义的栈段当作栈空间来访问。CPU只能看见栈顶。
  4. 栈段的最大可以设为:2的16次方,64KB
  5. 从栈操作指令所完成的功能的角度来看,pushpop指令在执行的时候只修改SP
  6. 我们可以将一段内存定义为一个段,用一个段地址指示段,用偏移地址访问段内的大暖,这完全是我们自己的安排。
  7. 对于代码段,我们将它的段地址放在CS中,将段中的第一条指令的偏移地址放在IP中,这样CPU就将执行我们定义的代码段中的指令。
  8. 对于栈段,我们将它的段地址放在SS中,将栈顶单元的偏移地址放在SP中,这样CPU在需要进行栈操作的时候,比如pushpop指令等,就将我们定义的栈段当作栈空间来用。
  9. CPU将内存中的某段内存当作代码,是因为CS:IP指向那里;CPU将某段内存当作栈,是因为SS:IP指向了那里。
    10.一段内存,可以既是代码的存储空间,又是数据的存储空间,还可以是栈空间,也可以什么都不是,关键在于CPU中寄存器的设置。

相关文章:

  • java中的IO流
  • 【每日一练】图解: 数组中的逆序对
  • 【Django】开发日报_8_Day:手机号码管理系统(6)
  • Quartz框架之Job和JobDetail(2)
  • C语言刷题(二)
  • 【毕业设计】机器学习股票大数据量化分析与预测系统 - python 毕业设计
  • Ubuntu下安装opencv
  • 手把手带你刷好题(牛客刷题⑦)
  • Java保证线程安全的方式有哪些?
  • 《数据结构》队列及其经典面试题
  • 计算机图形学(十一):真实感图形(光照模型、材质模型)
  • 【云原生】Hadoop HA on k8s 环境部署
  • 四元数是什么
  • 大衣哥家里再添喜事,生产厂家免费送给他一辆新车
  • 爬取疫情数据并存到mysql数据库
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • CentOS7 安装JDK
  • Kibana配置logstash,报表一体化
  • LintCode 31. partitionArray 数组划分
  • Redis中的lru算法实现
  • Sass Day-01
  • vuex 学习笔记 01
  • zookeeper系列(七)实战分布式命名服务
  • 大快搜索数据爬虫技术实例安装教学篇
  • 分布式任务队列Celery
  • 高性能JavaScript阅读简记(三)
  • 给github项目添加CI badge
  • 基于遗传算法的优化问题求解
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 如何在GitHub上创建个人博客
  • 深度学习中的信息论知识详解
  • 实现菜单下拉伸展折叠效果demo
  • 数组的操作
  • 一个JAVA程序员成长之路分享
  • 一个项目push到多个远程Git仓库
  • 一些css基础学习笔记
  • Nginx实现动静分离
  • #控制台大学课堂点名问题_课堂随机点名
  • #每日一题合集#牛客JZ23-JZ33
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (react踩过的坑)antd 如何同时获取一个select 的value和 label值
  • (阿里云万网)-域名注册购买实名流程
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (排序详解之 堆排序)
  • (三)Honghu Cloud云架构一定时调度平台
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (三)终结任务
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (转)C#开发微信门户及应用(1)--开始使用微信接口
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)linux下的时间函数使用
  • (转)大型网站架构演变和知识体系
  • (转)详解PHP处理密码的几种方式
  • .Net - 类的介绍