zoukankan      html  css  js  c++  java
  • 段地址

    处理器负责执行指令,内存里面存着CPU要执行的指令。
    当CPU通电之后,CPU内部所有的寄存器会进行复位,比如初始化成0000H,CPU就从这个地址开始提取指令,当然这是举例。

    为了做某件事而编写的指令,当这样几条,几十条,甚至几百万条,几千万条这样的程序组合在一起,形成了我们平时所说的程序。
    程序总要操作大量的数据,这些数据也应该集中在一起,位于内存中的某个地方,形成一个段,叫做数据段。


    假定我们有16个数要相加,这些数都是16位的二进制数,分别是0005H、00A0H、00FFH、…。
    为了让处理器把它们加起来,我们应该先在内存中定义一个数据段,将这些数字写进去。数据段可以起始于内存中的任何位置,既然如此,我们将它定在0100H处。

    这样一来,第一个要加的数位于地址0100H,第二个要加的数位于地址0102H,最后一个数的地址是011EH。
    一旦定义了数据段,我们就知道了每个数的内存地址。然后,紧挨着数据段,我们从内存地址0120H处定义代码段。

    严格地说,数据段和代码段是不需要连续的,但这里把它们挨在一起更自然一些。为了区别数据段和代码段,我们使用了不同的底色。


    代码段是从内存地址0120H处开始的,第一条指令是A1 00 01,其功能是将内存单元0100H里的字传送到AX寄存器。指令执行后,AX的内容为0005H。
    第二条指令是03 06 02 01,功能是将AX中的内容和内存单元0102H里的字相加,结果在AX中。由于AX的内容为0005H,而内存地址0102H里的数是00A0H,这条指令执行后,AX的内容为00A5H。
    第三条指令是03 06 04 01,功能是将AX中的内容和内存单元0104H里的字相加,结果在AX中。此时,由于AX里的内容是00A5H,内存地址0104H里的数是00FFH,本指令执行后,AX的内容为01A4H。
    图2-






    我们的程序OK,搞定了。
    但是平常我们使用计算机的时候,游戏,视频,操作系统已经把内存占用了。

    当我们在操作系统里面,双击一个这样的程序运行的时候,它很可能压根不会运行成功。
    因为操作系统,会考虑哪里的内存比较空闲,就把这些指令放到哪里去。
    可能把我们这些数据段和代码段放到了1000H的内存地址。

    而我们指令相加的内存地址却是0100……0104.。这肯定就出问题了。。








    我们让指令运行的时候,定位数据用的是绝对的内存地址。
    这样子程序真正执行的知道,被操作系统不知道分配到哪个内存位置了,就出问题了。

    所以,我们只能使用相对地址。
    当然,CPU的设计者们也为我们考虑到这些问题了,那么如何解决这个问题呢?


    在8086 16位CPU中,除了我们刚才学习的几个通用寄存器,再介绍两个寄存器,这两个寄存器分别为:
    代码段寄存器  CS  [Code Segment]
    数据段寄存器  DS  [Data Segment]
    附加段几次器  ES  [Extra Segment]
    指令寄存器     IP   它和CS一起使用。

    栈段寄存器    SS 










    当CPU要运行我们程序的时候,首先把CS和DS的位置确定下来,然后放到这两个寄存器里面。
    CS和IP共用形成逻辑地址,并经过CPU的一个部件变成物理地址来取得指令。
    访问内存则使用DS加偏移

    按照套路8086应该最大只有64KB内存。
    但是64KB太小了。

    内存的大小取决于CPU可以定位的范围和物理内存本身的大小。


    0000 0000 0000 0000
    1111 1111 1111 1111  地址定位
    FFFF = 65536 =64KB的内存
    1111 1111 1111 1111 1111  地址定位。 

    这样子可以定位1MB的内存.
    00000H到FFFFFH

    而寄存器却都是16位的。
    CS:0008
    IP: 0003
    CS:IP= 0008:0003 =000B 真实的内存物理地址。

    但却是00080:0003=00083




    所以,这个问题可以这样理解。
    我有两个16位寄存器最大都可以表示 FFFF
    现在我要通过这两个寄存器的组合,能够表示FFFFF


    为了让大家能够理解这种工作模式,我们转换成十进制给大家理解。

    A最大可以表示9999,最小为0000 
    B最大可以表示9999 , 最小为0000
    C最大可以表示99999,最小为00000

    我们怎么样可以用A和B来表示C呢?
    假如A是1230,B是80
    那么A x 10 + B= 12300+80 =12380

    A和B   C
    9999:0009   99999
    9999:0008   99998
    9999:0007   99997
    9999:0006   99996
    9999:0005   99995
    9999:0004   99994
    9999:0003   99993
    9999:0002   99992
    9999:0001   99991
    9999:0000   99990
    ...   ...
    ...   ...
    ...   ...
    0001:0009   00019
    0001:0008   00018
    0001:0007   00017
    0001:0006   00016
    0001:0005   00015
    0001:0004   00014
    0001:0003   00013
    0001:0002   00012
    0001:0001   00011
    0001:0000   00010
    0000:0009   00009
    0000:0008   00008
    0000:0007   00007
    0000:0006   00006
    0000:0005   00005
    0000:0004   00004
    0000:0003   00003
    0000:0002   00002
    0000:0001   00001
    0000:0000   00000

    十六进制

    A和B   C
    FFFF:000F   FFFFF
    FFFF:000E   FFFFE
    FFFF:000D   FFFFD
    FFFF:000C   FFFFC
    FFFF:000B   FFFFB
    FFFF:000A   FFFFA
    FFFF:0009   FFFF9
    FFFF:0008   FFFF8
    FFFF:0007   FFFF7
    FFFF:0006   FFFF6
    FFFF:0005   FFFF5
    FFFF:0004   FFFF4
    FFFF:0003   FFFF3
    FFFF:0002   FFFF2
    FFFF:0001   FFFF1
    FFFF:0000   FFFF0
    ...   ...
    ...   ...
    ...   ...
    0001:000F   0001F
    0001:000E   0001E
    0001:000D   0001D
    0001:000C   0001C
    0001:000B   0001B
    0001:000A   0001A
    0001:0009   00019
    0001:0008   00018
    0001:0007   00017
    0001:0006   00016
    0001:0005   00015
    0001:0004   00014
    0001:0003   00013
    0001:0002   00012
    0001:0001   00011
    0001:0000   00010
    0000:000F   0000F
    0000:000E   0000E
    0000:000D   0000D
    0000:000C   0000C
    0000:000B   0000B
    0000:000A   0000A
    0000:0009   00009
    0000:0008   00008
    0000:0007   00007
    0000:0006   00006
    0000:0005   00005
    0000:0004   00004
    0000:0003   00003
    0000:0002   00002
    0000:0001   00001
    0000:0000   00000
    0000:0000-0000:000F
    0001:0000-1000:000F
    0002:0000-0002:000F
    FFFF:0000-FFFF:000F

    把1M的内存分成了65536个段,每个段16个字节。


    当然,这只是一种组合定位物理地址的方法。
    我们还可以这么定位。
    0000:0000 - 0000:FFFF
    1000:0000 - 1000:FFFF
    2000:0000 - 2000:FFFF
    F000:0000 -F000:FFFF 

    把1M的内存分成了16个段,每个段64KB

    这是两种不同的分法:
    比如FFFF:000F和F000:FFFF其实是一个物理地址。


    假设现在物理地址00000H-82251H都被其他程序占用了。
    二后面82252H-FFFFFH,都是空闲的。
    为了让我们的程序能够加载。
    我们可以选择82260H这个位置。然后把DS:偏移设置成8226H:0000H
    因为我们要让偏移的初值地址为0000
  • 相关阅读:
    【转载】关于Java String, StringBuilder, StringBuffer, Hashtable, HashMap的面试题
    LeetCode: 【L4】N-Queens 解题报告
    【转载】在美国找工作秘籍
    Lintcode: Kth Largest Element 解题报告
    LeetCode: Reverse Integer 解题报告
    Lintcode: First Bad Version 解题报告
    九章面试题:Find first K frequency numbers 解题报告
    tomcat之虚拟目录
    百度搜索结果如何屏蔽百家号内容
    CentOS7之Rsync+Inotify架构实现实时同步文件和文件夹
  • 原文地址:https://www.cnblogs.com/xiaodaxiaonao/p/7135232.html
Copyright © 2011-2022 走看看