精华内容
下载资源
问答
  • 寄存器、段选择子、全局描述符表、局部描述符表、段描述符、线性地址;  保护模式下使用段机制的CS,SS,DS,ESt,FS,GS保存的并不是实模式下的段地址,而是一个包含了段选择子和偏移地址的组合值。CPU在读取...
    关键字:
    段寄存器、段选择子、全局描述符表、局部描述符表、段描述符、线性地址;

        保护模式下使用段机制的CS,SS,DS,ESt,FS,GS保存的并不是实模式下的段地址,而是一个包含了段选择子和偏移地址的组合值。CPU在读取内存的时候,需要将段寄存器的值解析成为段地址,才能定位找到相应的段。下面我们一步一步解析这个过程。
        知识点:
        段寄存器值=段选择子,简单来说,段选择子就是用来指定段描述符的位置的一个值。



        段选择子格式:


    低0-1位表示特权级,为减少复杂度,目前不关注。低第2位表示指定的是描述符表是GDT(0)还是LDT(1),第3-15位指示段描述符在段描述表中的序号,很关键。

        全局描述符表,一个系统只有一个全局描述符表,用来存放一些全局的段描述符(下面有讲述这个术语)。全局描述符表第一个项值规定是空值。全局描述符表的首地址由GDTR寄存器给出,这个值是线性地址,不需要解析。

        GDTR的是一个48位的值,16-47位范围共32位(Base Address)的GDT基地址,0-15位范围共16位(Limit)表示GDT表的大小(以字节计算)。
           在windbg内核模式,可以用r gdtr命令列出32位的基地址,用rgdtl列出16位的GDT大小值。

               r gdtr列出base address 指出段描述符表的基地址,是以平坦线性模式的地址显示,这个是其他段地址使用段选择子的基础。
               r gdtl列出limit以字节为单位,如果limit是1023,则包含1024个字节,GDT包含共有1024/8=128项段描述符。

        段描述符:共64位值,下图中的下部分是低32位,上部分是高32位。此段描述符中指出的段地址为:(32:24)(23:16)(15:00)这个值(共32位),就是我们所求的线性段地址了。


    局部描述符表寄存器LDTR表示当前任务的LDT表在GDTR中的索引,其格式是典型的段选择子。(结合全局描述符表理解)



    段机制和页机制一起工作原理示意图,页基制需要另一篇文章详细介绍。


    使用windbg来做上述过程的实验:
    1. 使用r命令列出寄存器值
    kd> r
    eax=00000001 ebx=00000000 ecx=8080a188 edx=8292eadc esi=8080a188 edi=00000029
    eip=82868bc0 esp=8292eaf8 ebp=8292eca4 iopl=0         nv up ei pl nz na po nc
    cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00200202
    2. 以cs为例,因为其值0008是段寄存器值=段选择子,我们使用.formats命令显示二进制数
    kd> .formats 0008
    Evaluate expression:
      Hex:     00000008
      Decimal: 8
      Octal:   00000000010
      Binary:  00000000 00000000 00000000 00001000
      Chars:   ....
      Time:    Thu Jan 01 08:00:08 1970
      Float:   low 1.12104e-044 high 0
      Double:  3.95253e-323
    第2位为0,表示使用的是全局描述符表,我们使用r gdtr命令查看全局描述符表的首地址。
    kd> r gdtr
    gdtr=80b95000

    第3-15位值为1,表示使用的是全局描述符表的第1个项(从0开始,第0项一定为0);我们查看全局描述符表的内容:
    kd> dd 80b95000
    80b95000  00000000 00000000 0000ffff 00cf9b00
    80b95010  0000ffff 00cf9300 0000ffff 00cffa00
    80b95020  0000ffff 00cff300 600020ab 80008b1c
    80b95030  1c003748 82409393 00000fff 0040f200
    80b95040  0400ffff 0000f200 00000000 00000000
    80b95050  f0000068 82008992 f0680068 82008992
    80b95060  00000000 00000000 00000000 00000000
    80b95070  500003ff 800092b9 00000000 00000000
    可见第0项的确为0,第一项内容为0000ffff 00cf9b00。根据段描述符的格式,段描述符中指出的段地址为:(32:24)(23:16)(15:00)这个值(共32位)为线性地址。
    kd> .formats 0000ffff
    Evaluate expression:
      Hex:     0000ffff
      Decimal: 65535
      Octal:   00000177777
      Binary:  00000000 00000000 11111111 11111111
      Chars:   ....
      Time:    Fri Jan 02 02:12:15 1970
      Float:   low 9.18341e-041 high 0
      Double:  3.23786e-319
    kd> .formats 00cf9b00
    Evaluate expression:
      Hex:     00cf9b00
      Decimal: 13605632
      Octal:   00063715400
      Binary:  00000000 11001111 10011011 00000000
      Chars:   ....
      Time:    Sun Jun 07 19:20:32 1970
      Float:   low 1.90656e-038 high 0
      Double:  6.72208e-317
    得出(32:24)(23:16)(15:00)这三个地方的值都为0,所以找到的线性段地址为0。也就是cs=0008指定的线性段地址为0.
    我们为验证结果,使用dg命令查看段选择子所指定的段描述符的内容
    kd> dg 0008
                                      P Si Gr Pr Lo
    Sel    Base     Limit     Type    l ze an es ng Flags
    ---- -------- -------- ---------- - -- -- -- -- --------
    0008 00000000 ffffffff Code RE Ac 0 Bg Pg P  Nl 00000c9b
    结果正确。
    3. 再以fs=0030为例验证。
    kd> .formats 0030
    Evaluate expression:
      Hex:     00000030
      Decimal: 48
      Octal:   00000000060
      Binary:  00000000 00000000 00000000 00110000
      Chars:   ...0
      Time:    Thu Jan 01 08:00:48 1970
      Float:   low 6.72623e-044 high 0
      Double:  2.37152e-322
    可见低第2位为0,指定的是全局描述符表。同样使用r gdtr找全局描述符基地址,然后定位第110b的段描述符:
    kd> r gdtr
    gdtr=80b95000
    kd> dd 80b95000+6*8 l2
    80b95030  1c003748 82409393
    kd> .formats 1c003748 
    Evaluate expression:
      Hex:     1c003748
      Decimal: 469776200
      Octal:   03400033510
      Binary:  00011100 00000000 00110111 01001000
      Chars:   ..7H
      Time:    Tue Nov 20 13:23:20 1984
      Float:   low 4.24231e-022 high 0
      Double:  2.321e-315
    kd> .formats 82409393
    Evaluate expression:
      Hex:     82409393
      Decimal: -2109697133
      Octal:   20220111623
      Binary:  10000010 01000000 10010011 10010011
      Chars:   .@..
      Time:    ***** Invalid
      Float:   low -1.41483e-037 high -1.#QNAN
      Double:  -1.#QNAN
    得出的线性段地址二进制值为:  10000010    10010011     00011100 00000000   B
    转变为16进制为:82931c00;
    使用dg来验证线性段地址:
    kd> dg 30
                                      P Si Gr Pr Lo
    Sel    Base     Limit     Type    l ze an es ng Flags
    ---- -------- -------- ---------- - -- -- -- -- --------
    0030 82931c00 00003748 Data RW Ac 0 Bg By P  Nl 00000493
    结果正确。

    参考资料:
    Intel64 and IA-32 Architectures Software Developer's Manual.pdf
    张银奎《软件调试》

    展开全文
  • 在SL低电平且SCK上升沿的时候,将串行数据SDATA存入寄存器里(要求存入D0之后的数据,A0、A1、A2及TEST BIT不存入寄存器)。并且,SL由高电平转为低电平后,数据重新从寄存器的第一位开始存。
  • 一、寄存器地址映射 二、寄存器各位定义 三、中断号定义 关于一,怎么说呢,可以参考一下《STM32F4开发指南——库函数版本》里边的4.6小节“MDK中寄存器地址名称映射分析”,这篇文章介绍的比较清楚,其中需要...

    如何实现:

    一、寄存器地址映射

    二、寄存器各位定义

    三、中断号定义

    关于一,怎么说呢,可以参考一下《STM32F4开发指南——库函数版本》里边的4.6小节“MDK中寄存器地址名称映射分析”,这篇文章介绍的比较清楚,其中需要注意的是什么呢:

    1. STM32,我想顾名思义,这个32可能也是表明他的寄存器都是32位的吧,这样的话每一个寄存器就都可以有bit0~bit31,也就是4个连续的字节,比如0x00,0x01,0x02,0x03。因此寄存器的偏移地址0x00,0x04,0x08。。。

    2. 刚才提到了连续,那各个寄存器之间也要用连续的地址才行,什么样的数据结构可以保证地址连续呢?就是结构体类型,结构体类型的成员变量地址具有连续性。

    3. 将地址强制转换为结构体指针~~将结构体与寄存器地址对映上

    关于二,寄存器各个位如何定义,看一下下图就知道了

     

    关于三,中断号如何定义,也是用结构体,其中需要注意的是Cortex-M处理器本身有中断,中断号是-14 ~ -1。

     

     

     

    展开全文
  • 【STM32】MDK中寄存器地址名称映射分析

    万次阅读 多人点赞 2018-04-04 18:11:07
    51单片机访问地址 51单片机经常会引用一个reg51.h的头文件。下面看看它是怎么把名字和寄存器联系在一起的: sfr p0=0x80; p0=0x00; sfr是一种扩充数据类型,点用一个内存单位,值域为0-255....

    对于MCU,一切底层配置,最终都是在配置寄存器。

    STM32F1xx官方资料:
    《STM32中文参考手册V10》-第8章通用和复用功能IO(GPIO和AFIO)

     

    51单片机访问地址

    51单片机经常会引用一个reg51.h的头文件。下面看看它是怎么把名字和寄存器联系在一起的:

    sfr p0=0x80;
    p0=0x00;

    sfr是一种扩充数据类型,点用一个内存单位,值域为0-255.利用它可以访问51单片机内部所有的特殊功能寄存器。前一句“sfr p0=0x80”就是将P0映射到地址0x80。后一句“p0=0x00”就是往p0地址(0x80)代表的寄存器写值。

     

    STM32访问地址

    寄存器地址名称映射

    STM32肯定也是可以这样来设置寄存器的。但是由于STM32的寄存器数目太多了,如果以这样的方式列出来,需要很大的篇幅,而且也不方便开发。所以,MDK采用的方式是通过结构体来将寄存器组织在一起。

    下面就介绍MDK如何把结构体和地址对应起来的,为什么修改结构体成员变量的值就可以达到操作寄存器的值?这些事情都是在stm32f10x.h文件中完成的。

    注:stm32f10x.h文件在STM32固件库下的目录是:

    STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x文件夹下。

    GPIOA的寄存器地址名称映射

    我们通过GPIOA的寄存器为例来进行介绍。

    GPIOA->ODR=0x00000000;

    首先,我们需要看一下GPIOA是个什么东西?通过宏定义我们可以看到:

    #define GPIOA               ((GPIO_TypeDef *) GPIOA_BASE)
    #define GPIOB               ((GPIO_TypeDef *) GPIOB_BASE)
    #define GPIOC               ((GPIO_TypeDef *) GPIOC_BASE)
    #define GPIOD               ((GPIO_TypeDef *) GPIOD_BASE)
    #define GPIOE               ((GPIO_TypeDef *) GPIOE_BASE)
    #define GPIOF               ((GPIO_TypeDef *) GPIOF_BASE)
    #define GPIOG               ((GPIO_TypeDef *) GPIOG_BASE)

    GPIOA是一个将GPIOA_BASE强制转换成GPIO_TypeDef的指针。这句话的意思就是,GPIOA指向地址GPIOA_BASE,而GPIOA_BASE存放的数据类型是GPIO_TypeDef。再看一下结构体GPIO_TypeDef的定义:

    typedef struct
    {
      __IO uint32_t CRL;
      __IO uint32_t CRH;
      __IO uint32_t IDR;
      __IO uint32_t ODR;
      __IO uint32_t BSRR;
      __IO uint32_t BRR;
      __IO uint32_t LCKR;
    } GPIO_TypeDef;

    结构体里面声明了7个变量,这个时候就明白了“GPIOA->ODR”就是指:GPIOA结构体下的ODR变量。

    其实结构体的7个变量就是GPIOA的7个寄存器。我们需要知道GPIOA下的ODR寄存器的地址,首先需要知道的是GPIOA的基地址是怎么计算的呢?

    #define GPIOA_BASE            (APB2PERIPH_BASE + 0x0800)
    #define GPIOB_BASE            (APB2PERIPH_BASE + 0x0C00)
    #define GPIOC_BASE            (APB2PERIPH_BASE + 0x1000)
    #define GPIOD_BASE            (APB2PERIPH_BASE + 0x1400)
    #define GPIOE_BASE            (APB2PERIPH_BASE + 0x1800)
    #define GPIOF_BASE            (APB2PERIPH_BASE + 0x1C00)
    #define GPIOG_BASE            (APB2PERIPH_BASE + 0x2000)

    因为GPIO都是挂载在APB2总线之上的,所以它的基地址是由APB2总线的基地址+GPIO在APB2总线上的偏移地址决定的。那么APB2总线的基地址是怎么计算的呢?

    #define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
    #define APB2PERIPH_BASE       (PERIPH_BASE + 0x10000)

    原理都是一样的,APB2总线的基地址也是从其他地址进行地址偏移得到的。

    所以到这个时候,就可以算出GPIOA的基地址位了:

    GPIOA_BASE=0x40000000+0x10000+0x0800=0x40010800

    这上面就已经知道了GPIOA的基地址,那么那些GPIOA的7个寄存器的地址又是怎么计算出来的呢?

    GPIOA的寄存器的地址=GPIOA基地址+寄存器相对GPIOA基地址的偏移值

    寄存器相对于GPIOA基地址的偏移值可以在上面的寄存器地址映射表中查到。稍微解释一下:GPIO的每个寄存器都是32位的,所以每个寄存器是占用4个地址,也就是说一共占用28个地址。地址偏移范围为(000h-01Bh)。这个地址偏移是相对于GPIOA的基地址而言的。

    那么你可能又有一个疑问:结构体里面的寄存器又是怎么与地址一一对应的呢?这就涉及到结构体的一个特征,那就是结构体存储的成员的地址是连续的。上面讲到GPIOA是指向GPIO_TypeDef类型的指针,又由于GPIO_TypeDef是结构体,所以自然而然我们就可以算出GPIOA指向的结构体成员变量对应地址了。

     

    总结与分析

    对于STM32而言,使用“GPIOA->ODR=0x00000000;”来对寄存器赋值的原理,也就是将GPIO下的所有寄存器放在一个结构体内,通过基地址和在基地址上的偏移地址不断转化,最终找到准确的寄存器实际地址来进行赋值。也就是说,和51单片机最大的不同就是:由于STM32的寄存器数目太多,就将其中控制同一外设的寄存器设置成一个结构体(如GPIO、DMA等),通过对结构体的地址和寄存器相对于结构体的偏移地址,来确定某个特定的寄存器。

     

    展开全文
  • 寄存器地址并转换为16位地址类型

    千次阅读 2020-01-07 20:11:57
    寄存器 地址 FPROTSL 地址 &FTFx_FPROTSL_REG -> 为32位, 所以在将地址转为数据时应转换为32位数据 ->(uint32_t)&FTFx_FPROTSL_REG 然后再将其32位数据转为16位的地址 -> (volatile uint16_t *)(uint32_t)&...
    typedef struct {
    
    __IO uint8_t FPROTSL;                           
    __IO uint8_t FPROTSH;   
    } FTFE_Type;
    
    #define FTFx     ((FTFE_Type *)FTFE_BASE)
    
    #define FTFx_FPROTSL_REG (FTFx->FPROTSL)
    
    static volatile uint16_t *const kFPROTSx = (volatile uint16_t *)(uint32_t)&FTFx_FPROTSL_REG;

    取寄存器 地址  FPROTSL 地址 &FTFx_FPROTSL_REG -> 为32位, 所以在将地址转为数据时应转换为32位数据 ->(uint32_t)&FTFx_FPROTSL_REG

    然后再将其32位数据转为16位的地址 -> (volatile uint16_t *)(uint32_t)&FTFx_FPROTSL_REG;

    最后将16位地址指针 赋给 volatile uint16_t *const kFPROTSx 指针

    展开全文
  • #define GPIOE ((GPIO_TypeDef *) GPIOE_BASE) //强制转化为指针后,这些宏定义的常量才具有的地址的属性,因为指针就是地址//强制转化为结构指针类型后,这些常量的宏定义也就具有结构类型的地址2020.2.24 ...
  • 1.STM32中的存储器映射地址(查STM32F429数据手册) /*片上外设基地址*/ #define PERIPH_BASE ((unsigned int)0x40000000) /*AHB1总线基地址*/ #define AHB1PERIPH_BASE (PERIPH_BASE + 0x00020000) /*GPIOB基...
  • 寄存器

    2010-11-28 20:11:00
    寄存器:   寄存器是中央处理器内的组成部分。...地址寄存器AR 3.缓冲寄存器DR 4.指令寄存器IR 5.微地址寄存器μAR 6. 微指令寄存器μIR7.状态指令寄存器SR(statu
  • CAN0TXIDR0是八位寄存器,而计算出的TX_ID是32位 如果上面这一语句把八位寄存器强制转化为32位,那么 多出来的24位是直接赋值到接下来的24位吗?
  • Cs是代码段寄存器,IP是指令指针寄存器地址 x 16 等于 左移四位 一个数据(16进制)左移1位,相当于乘以16。 一个数据 (十进制)左移1位,相当于乘以10。 一个数据(N进制) 左移1位 ,相当于乘以N。 段地址...
  • 首先将需要读取的PLC内部元件的地址找到,主要内部元件地址如下: D: PLC-Address*2+1000H; T: PLC-Address+00C0H; C: PLC-Address*2+01C0H; S: PLC-Address*3; M: PLC-Address*2+0100H; Y: PLC-Ad...
  • RAM寄存器习题

    2015-04-13 22:54:47
    RAM寄存器简单习题,包括内存与寄存器地址转化,用汇编语言。
  • 寄存器映射

    2020-09-22 22:34:49
    但是电脑不知道它地址,因此需要在前面加一个(unsigned int *)对其进行强制类型转换,这个的作用就是把GPIOB_BASE + 0x00强制转化地址,因为*符号运算的是地址,所以(unsigned int *)(GPIOB_BASE + 0x00)这一串就...
  • WinCE下的地址映射以及寄存器访问
  • FreeModbus保持寄存器

    千次阅读 2019-04-08 21:39:22
    保持寄存器的访问属性为读写 对保持寄存器的操作包括:读保持寄存器(0x03)、写...请求PDU说明了起始寄存器地址寄存器数量。从零开始寻址寄存器。因此,寻址寄存器1-16 为0-15。 将响应报文中的寄存器数据...
  • 操作系统中页式地址转化

    万次阅读 2016-01-01 14:20:30
    操作系统中页式地址转化   关于地址转换  在计算机操作系统中,地址转换是存储管理的一个主要功能。所谓地址转换就是将用户的逻辑地址转换成内存的物理地址,完成地址重定位。需要指出的是,地址转换是操作...
  • 进制转化: 10进制—2进制—8进制—16进制 eg:125(10)——125(2)——125(8)——125(16) 128 64 32 16 8 4 2 1 125(2) 0 1 / 1 1 // 1 / 1 0 1 125(8) ...
  • ​字符串寄存器、字符串指令 注释:字符串寄存器,存储英文数字的字符串。各自的寄存器中,最多可以存储254个字符。字符串寄存器数标准为25个。 字符串寄存器数可在控制启动时增加。 SR[i] =(值) SR[i]=...
  • cpu寄存器

    2017-05-22 18:08:37
    CPU的寄存器能够对少量的数据进行快速的存取访问。 在x86指令集里, 一个CPU有 八个通用寄存器: EAX,EDX,ECX,ESI,EDI,EBP,ESP和 EBX。还有很多别的寄存器,遇 到的时候具体讲解。这八个通用寄存器各有不同的用途...
  • FreeModbus输入寄存器

    千次阅读 2019-04-08 21:22:32
    请求PDU 说明了起始地址寄存器数量。从零开始寻址寄存器。因此,寻址输入寄存器1-16 为0-15。 将响应报文中的寄存器数据分成每个寄存器为两字节,在每个字节中直接地调整二进制内容。对于每个寄存器,第一个字节...
  • PC机上,COM1和COM2的地址是3F8~3FF 及2F8~2FF,在这个范围内的每个地址都有不同的功能,这些功能分别通过寄存器来实现,读写这些寄存器就可以执行与串行端口相关的功能。而所谓的寄存器就是暂时存放信息的地方,...
  • PC机上,COM1和COM2的地址是3F8~3FF 及2F8~2FF,在这个范围内的每个地址都有不同的功能,这些功能分别通过寄存器来实现,读写这些寄存器就可以执行与串行端口相关的功能。而所谓的寄存器就是暂时存放信息的地方,...
  • 汇编中寄存器详解

    2021-05-10 15:19:22
    "字"在寄存器中的存储 8086是16位CPU,8086的字长为16bit 一个字可以存在一个16位寄存器中 ...先把要储存的数据转化成十六进制,再根据十六进制和二进制之间的转换关系转换成二进制储存到寄存器中20000D -- 4E20H .
  • 逻辑地址到物理地址转化 机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(Memory Management Unit,CPU中的内存管理单元)转换成物理地址才能够被访问到。 1、逻辑地址转化为线性...
  • 什么是寄存器

    2020-08-31 16:06:45
    专业的解释就看百度百科吧,这里是形象的比喻: 以下内容转自两名知乎用户: 寄存器就是你的口袋。...外存(比如硬盘)就是脂肪,容量可以非常大,性能很差,要先转化为葡萄糖(存进内存),然后转化
  • STM32的寄存器操作

    2021-03-28 21:23:25
    STM32的寄存器操作 在使用STM32单片机编程时一般都用ST给的库函数编程,库函数编程的底层就是对...1.每个寄存器都有一个地址,这个地址寄存器软件层面的映射,具有相互对应的关系,如: #define DAC_Trigger_T2_TRGO

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 39,643
精华内容 15,857
关键字:

寄存器地址转化