精华内容
下载资源
问答
  • 调试寄存器 原理与使用:DR0-DR7 下面介绍的知识性信息来自intelIA-32手册(可以在intel的开发手册或者官方网站查到),提示和补充来自学习调试器实现时的总结。 希望能给你带去有用的信息。 (DRx对应任意的一...

    调试寄存器 原理与使用:DR0-DR7

    下面介绍的知识性信息来自intel IA-32手册(可以在intel的开发手册或者官方网站查到),提示和补充来自学习调试实现时的总结。

    希望能给你带去有用的信息。

    (DRx对应任意的一个调试寄存。LENn对应任意一个长度。Ln对应任意一个局部置位)

    DR0-DR7可以直接被读写操作(MOV 指令之类的,DRx可以是源操作数也可以是目的操作数)

       但是,DRx的访问是需要一定权限的。比如你用MOV操作的话,你需要在实地址模式,系统管理模式(smm)或者在保护模式(CPL设0).如果权限不够,将会在访问DRx的时候尝产生#GP(general-protection)异常

    现在来看看DRx可以干些什么? 

    1.设置发生断点的地址(线性地址)
    2.设置断点的长度(1,2,4个字节,但是执行断点只能是1)
    3.设置在调试异常产生的地址执行的操作
    4.设置断点是否可用
    5.在调试异常产生时,调试条件是否是可用

    (以上直接翻译自"Intel 64 and IA-32 Architectures Software Developer’s Manual" volume 3。
    以下来自个人的总结。当然,也是参考intel官方资料得来的)

    我们来看看调试寄存的一些细节信息。
    下图很重要,后面的介绍都是针对这个图说的。
    (当然不是我画的,是来自intel  ia-32系统结构开发手册18章2节)。

    点击图片以查看大图图片名称: DR0_DR7.jpg查看次数: 2105文件大小: 63.6 KB文件 ID : 39226

    调试寄存 DR0-DR3
       这四个寄存是用来设置 断点地址的。断点的比对在物理地址转换前(异常产生时,还没有将线性地址转换成物理地址)。由于只有0-3四个保存地址的寄存,所以,硬件断点,在物理上最多只能有4个。
    调试寄存DR4-DR5 
       这两个调试寄存有CR4的DE标记控制。如果DE置位,那么对这两个寄存的访问会导致#UD异常。如果DE置0,那么他们就被化名为DR6-DR7(你一定会问原来的DR6-DR7怎么办?这个…… 我也不知道。如果你搞明白了,一定记得告诉我)
    调试寄存DR7(控制寄存)
       (先介绍DR7对DR6的理解有好处。)

    DR7是调试控制寄存。控制方式嘛!继续看:
    1.  L0-L3(由第0,2,4,6位控制):对应DR0-DR3,设置断点作用范围,如果被置位,那么将只对当前任务有效。每次异常后,Lx都被清零。
    2.  G0-G3(由第1,3,5,7位控制):对应DR0-DR3,如果置位,那么所有的任务都有效。每次异常后不会被清零。以确保对所有任务有效。但是,不知道为什么,我在测试时:
    设置Gn后,不能返回调试异常给调试(如果你知道为什么,记得告诉我)
    3.  LE,GE(由第8,9位控制):这个在P6以下系列CPU上不被支持,在升级版的系列里面:如果被置位,那么cpu将会追踪精确的数据断点。LE是局部的,GE是全局的。(到底什么算精确的,我也不清楚,但是,我知道如果设置了这两个,cpu的速度会降低。我在测试中,都没有置位。)
    4.  GD(由第13位控制):如果置位,追踪下一条指令是否会访问调试寄存。如果是,产生异常。在下面的DR6里面,你会知道他还和另外一个标志位有点关系。
    5.  R/W0-R/W3:(由第16,17,20,21,24,25,28,29位控制):这个东西的处理有两种情况。
    如果CR4的DE被置位,那么,他们按照下面的规则处理问题:
    00:执行断点
    01:数据写入断点
    10:I/0读写断点
    11:读写断点,读取指令不算
    如果DE置0,那么问题会这样处理:
    00:执行断点
    01:数据写入断点
    10:未定义
    11:数据读写断点,读取指令不算
    6.  LEN0-LEN3:(由第18.19.22.23.26.27.30位控制):指定内存操作的大小。
    00:1字节(执行断点只能是1字节长)
    01:2字节
    10:未定义或者是8字节(和cpu的系列有关系)
    11:4字节
    调试寄存DR6(调试状态寄存
       这个寄存主要是在调试异常产生后,报告产生调试异常的相关信息
    1.  B0-B3(DR0-DR3):DRx指定的断点在满足DR7指定的条件下,产生异常。那么Bx就置位。但是,有时,即使Ln和Gn置0,也可能产生Bx被置位。这种现象可能这样出现(提示:在p6系列处理,REP MOVS在不断循环中产生的调试异常需要执行完了才能准确返回给调试进程):DR0的L0,G0都置0(DR0就是一个不能产生异常的断点了),然后在DR0指定的地址是一个REP指令的循环,这样,DR0就可能在这个循环之后的REP指令产生的调试异常中将B0置位
    2.  BD:BD需要DR7的GD置位,才有效。BD是在下一条指令要访问到某一个调试寄存的时候,被置位的。
    3.  BS:单步执行模式时,被置位。单步执行是最高权限的调试异常。
    4.  BT:在任务切换的时候,被置位。但是必须在被切换去的任务的TSS段里面的T标记被置位的情况下才有效。在控制权被切换过去后,在执行指令前,返回调试异常。但是,需要注意,如果调试程序是一个任务,那么T标记的设置肯定就冲突了。然后,导致了死循环(BT的这些信息都是按照官方资料翻译而来,由于没有实际的操作,肯定会有理解上的出入。如果要深入的话,建议看官方资料)
      
    有些调试异常会将B0-B3清零。但是其他的DR6的位是不能被产生异常的进程清零的。每次调试异常返回后,调试进程都会先将DR6清零,再按照情况设置。以免产生不必要的错误。

    对齐问题和64位处理
    对齐问题:
    这个问题是来源于LENn的设置,如果设置4字节,那么必须4字节对齐。例如:我们下4字节的断点,那么DRx需要是A0000/A0004/A0008这样的地址上。I/O地址是零扩展的(这个……也许意味着必须完全对齐)。因为,intel在比对地址时:用LENn的值去覆盖DRx里面保存的地址的低位。你可以想到,不对齐会有什么后果了吧。注意:执行断点只能是1字节。

    再用图片解释下(当然,图片来自intel官方资料):

    点击图片以查看大图图片名称: Align1.jpg查看次数: 2083文件大小: 68.6 KB文件 ID : 39224
    点击图片以查看大图图片名称: Align2.jpg查看次数: 2073文件大小: 33.1 KB文件 ID : 39225

    在64位处理下:
    调试寄存当然也是64位的。在操作过程中,写入,前面32位被置零。读取:只返回后32位。MOV DRx操作,前32位被忽略。
    DR6-DR7的高32位被保留。置零。如果置位,会产生#GP异常。8字节的读写断点完全被支持。

    最后,还是给个图片(64位处理的布局):

    点击图片以查看大图图片名称: 64.jpg查看次数: 2074文件大小: 41.9 KB文件 ID : 39223

    最后需要提醒一个小问题:数据写入断点设置后。是在原数据被修改后,才产生调试异常。所以,返回异常时,原有数据已经被修改。如果想保留原有数据,需要自己提前保存对应地址的数据。

     

    VC利用调试寄存器实现硬件断点,处理断点异常

     

    1.  
      /************************************************************************
    2.  
      SetHardWareBP:
    3.  
      设置线程硬件断点
    4.  
      hThread: 线程句柄
    5.  
      dwAddr: 断点地址
    6.  
      dwDrIndex: 硬件寄存器(0~3)
    7.  
      nType: 断点类型(0:执行,1:读取,2:写入)
    8.  
      nLen: 读写断点数据长度(1,2,4)
    9.  
      /************************************************************************/
    10.  
       
    11.  
      BOOL SetHardWareBP(HANDLE hThread,DWORD dwAddr,DWORD dwDrIndex=0,UINT nType=0,UINT nLen=1)
    12.  
      {
    13.  
      BOOL bResult=FALSE;
    14.  
       
    15.  
      CONTEXT context = {0};
    16.  
      context.ContextFlags=CONTEXT_DEBUG_REGISTERS;
    17.  
      if(::GetThreadContext(hThread,&context))
    18.  
      {
    19.  
      DWORD dwDrFlags=context.Dr7;
    20.  
       
    21.  
       
    22.  
      //将断点地址复制进入对应Dr寄存器(参考CONTEXT结构)
    23.  
      memcpy(((BYTE *)&context)+4+dwDrIndex*4,&dwAddr,4);
    24.  
       
    25.  
      //决定使用哪个寄存器
    26.  
      dwDrFlags|=(DWORD)0x1<<(2*dwDrIndex);
    27.  
       
    28.  
      //见OD读写断点时 这个置位了,执行没有(置位也正常-_-)
    29.  
      dwDrFlags|=0x100;
    30.  
       
    31.  
       
    32.  
      //先将对应寄存器对应4个控制位清零(先或,再异或,还有其它好方法吗) =.= 悲催的小学生
    33.  
      dwDrFlags|=(DWORD)0xF<<(16+4*dwDrIndex);
    34.  
      dwDrFlags^=(DWORD)0xF<<(16+4*dwDrIndex);
    35.  
       
    36.  
       
    37.  
      //设置断点类型,执行:00 读取:11 写入:01
    38.  
      //(不知何故,测试时发现不论是11还是01,读写数据时均会断下来)
    39.  
      if (nType==1)
    40.  
      dwDrFlags|=(DWORD)0x3<<(16+4*dwDrIndex); //读取
    41.  
      else if(nType==2)
    42.  
      dwDrFlags|=(DWORD)0x1<<(16+4*dwDrIndex); //写入
    43.  
      //else if(nType==0)
    44.  
      //dwDrFlags=dwDrFlags //执行
    45.  
       
    46.  
       
    47.  
      //设置读写断点时数据长度
    48.  
      if (nType!=0)
    49.  
      {
    50.  
      if(nLen==2 && dwAddr%2==0)
    51.  
      dwDrFlags|=(DWORD)0x1<<(18+4*dwDrIndex); //2字节
    52.  
      else if(nLen==4 && dwAddr%4==0)
    53.  
      dwDrFlags|=(DWORD)0x3<<(18+4*dwDrIndex); //4字节
    54.  
      }
    55.  
       
    56.  
      context.Dr7=dwDrFlags;
    57.  
      if (::SetThreadContext(hThread,&context)) bResult=TRUE;
    58.  
      }
    59.  
      return bResult;
    60.  
      }

    1.  
      //异常处理
    2.  
      //直接从工程中拷出来的
    3.  
      typedef ULONG (WINAPI *pfnRtlDispatchException)(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext);
    4.  
      static pfnRtlDispatchException m_fnRtlDispatchException=NULL;
    5.  
       
    6.  
      BOOL RtlDispatchException(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext);
    7.  
       
    8.  
      ULONG WINAPI CSysHook::_RtlDispatchException( PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext )
    9.  
      {
    10.  
      if(RtlDispatchException(pExcptRec,pContext)) return 1;
    11.  
      return m_fnRtlDispatchException(pExcptRec,pContext);
    12.  
      }
    13.  
       
    14.  
      //Hook程序异常处理,当程序发生异常时,由ring0转回ring3时调用的第一个函数:KiUserExceptionDispatcher
    15.  
      BOOL CSysHook::HookSystemSEH()
    16.  
      {
    17.  
      BOOL bResult=FALSE;
    18.  
      BYTE *pAddr=(BYTE *)::GetProcAddress(::GetModuleHandleA("ntdll"),"KiUserExceptionDispatcher");
    19.  
      if (pAddr)
    20.  
      {
    21.  
      while (*pAddr!=0xE8)pAddr++; //XP~Win7正常,Win8尚无缘得见
    22.  
      m_fnRtlDispatchException=(pfnRtlDispatchException)((*(DWORD *)(pAddr+1))+5+(DWORD)pAddr); //得到原函数地址
    23.  
      DWORD dwNewAddr=(DWORD)_RtlDispatchException-(DWORD)pAddr-5; //计算新地址
    24.  
      CMemory::WriteMemory((DWORD)pAddr+1,(BYTE *)&dwNewAddr,4); //这个写内存的自己改造吧
    25.  
      bResult=TRUE;
    26.  
      }
    27.  
      return bResult;
    28.  
      }
    29.  
       
    30.  
      //异常处理函数
    31.  
      BOOL RtlDispatchException(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext)
    32.  
      {
    33.  
      返回TRUE,这个异常我已经处理好了,继续运行程序
    34.  
      返回FALSE,这个异常不是我的,找别人处理去
    35.  
      }
    详情jpg 转 rar

     

    转载于:https://www.cnblogs.com/kuangke/p/9397482.html

    展开全文
  • ST堆栈寄存器原理

    2010-01-11 20:54:00
    ST堆栈寄存器原理图 ST堆栈寄存器的作用,是出现中断或子程序调用时,保存断点处PC的值,以便中断或子程序结束时,能继续执行原程序。其原理图见2-10。 图2-10 ST堆栈寄存器原理图 图中,信号STE

                                                          ST堆栈寄存器原理图

     

    ST堆栈寄存器的作用,是出现中断或子程序调用时,保存断点处PC的值,以便中断或子程序结束时,能继续执行原程序。其原理图见2-10。

                          
     图2-10  ST堆栈寄存器原理图

               图中,信号STEN的作用是将数据总线DBUS上数据存入堆栈寄存器ST中。

    展开全文
  • GPIO寄存器原理与操作

    万次阅读 2018-08-05 22:01:46
    方式一:通过写操作直接控制位设置/清除寄存器而后到输出数据寄存器 方式二:通过读写操作直接到达输出数据寄存器 两种方式到达输出数据寄存器后到达输出控制(即一个锁存器),通过输出控制,可改变输出信号值。 ...

    一、GPIO内部结构

    输出数据:从芯片内部到芯片I/O端口

    方式一:通过写操作直接控制位设置/清除寄存器而后到输出数据寄存器

    方式二:通过读写操作直接到达输出数据寄存器

    两种方式到达输出数据寄存器后到达输出控制(即一个锁存器),通过输出控制,可改变输出信号值。

    eg:输出数据寄存器向输出控制(锁存器)输出信号1,则P-MOS处信号为1,N-MOS处信号为0,则输出Vdd高电平(3.3V),反之,输出数据寄存器向输出控制(锁存器)输出信号0,则P-MOS处信号为0,N-MOS处信号为1,则输出Vss低电平。

    输入数据:从芯片I/O端口到芯片内部(保护二极管可防止输入电平过高或过低对芯片内部电路造成损坏)

     

    通用功能I/O(GPIO)和复用功能I/O(APIO)

    GPIO功能描述:每个GPIO端口有两个32位配置寄存器(GPIOx_CRL,GPIOx

    _CRH,即上文所说的控制寄存器),两个32位数据寄存器(GPIOx_IDR,GPIOx_ODR),一个32位置位/复位寄存器(GPIOx_BSRR),一个16位复位寄存器(GPIOx_BRR)和一个32位锁定寄存器(GPIOx_LCKR)。

    根据数据手册中列出的每个I/O端口的特定硬件特征,GPIO端口的每个位可以由软件分别配置完成多种模式。

    输入浮空、输入上拉、输入下拉、模拟输入、

    开漏输出、推挽输出(P-MOS、N-MOS均正常工作)、推挽式复用功能、开漏式复用功能

    每个I/O端口位可以自由编程,然而I/O端口寄存器必需按32位字被访问(不允许半字或者字节访问),GPIOx_BSRR和GPIOx_BRR允许对任何GPIO寄存器的读/更改的独立访问,这样,在读和更改访问之间产生IRQ时不会发生危险。

    (CNF0最后一行应为1、0)

    通用I/O(GPIO)

    复位期间和刚复位后,复用功能未开启,I/O端口被配制成浮空输入模式(CNFx[1:0] = 01b,MODE[1:0] = 00b)

    复位后,JTAG引脚被置于输入上拉或下拉模式

    PA15:JTD1置于上拉模式

    PA14:JTCK置于下拉模式

    PA13:JTMS置于上拉模式

    PB4:JNTRST置于上拉模式

    当作为配置输出时,写到输出数据寄存器上的值(GPIOx_ODR)输出到相应的I/O引脚。可以以推挽模式或者开漏模式(当输出0时,只有N-MOS被打开)使用输出驱动器。

    输入数据寄存器(GPIOx_IDR)在每个APB2时钟周期捕捉I/O引脚上的数据)

    所有GPIO引脚有一个内部弱上拉和弱下拉,当配置为输入时,它们可以被激活也可以不被激活.

    单独的未设置或者位清除

    当对GPIOx_ODR的个别位编程时,软件不需要禁止中断,在单次APB2写操作里,可以只更改一个或者多个位。

    这是通过对“置位/复位寄存器”(GPIOx_BSRR)中想要该写位写1来实现的,没被选择的位则不被更改。

    所有的端口都有外部中断能力,为了使用外部中断线,端口必须配置成输入模式。

     

    输入配置:
    当I/O端口配置为输入时:

    输出缓冲器被禁止,施密特触发输入被激活,根据输入配置(上拉、下拉、浮空)的不同,弱上拉和下拉电阻被连接

    出现在I/O引脚上的数据在每个APB2时钟被采样到输入数据寄存器,对输入数据寄存器的读访问可得到I/O口的状态

    输出配置:

    当I/O端口被配置为输出时:

    输出缓冲寄存器被激活

    —开漏模式:输出寄存器上的0激活N-MOS,而输出寄存器上的1将端口置于高阻状态(P-MOS从不被激活)

    —推挽模式:输出寄存器上的0激活N-MOS,而输出寄存器上的1将激活P-MOS

    施密特触发输入被激活,弱上拉和下拉电阻被禁止,出现在I/O引脚上的数据在在每个APB2时钟被采样到输入数据寄存器,在开漏模式时,对输入数据寄存器的读即可得到I/O状态,在推挽模式时,对输入数据寄存器的读访问的得到最后一次写的值。

    eg:x = A;则CRL控制GPIOA的0 —15引脚的工作模式

    eg:x = A;则CRL控制GPIOA的8—15引脚的工作模式

      

    编程:一、

    1、设置GPIOA引脚的工作模式,GPIOA.0,GPIO.1,推挽输出,速度50MHz

     GPIOA->CRL = 0x33;

    2、在相应的引脚输出一个电平

    GPIOA->ODR = 0x0;   //00

    GPIOA->DDR = 0x3;   //11

     二、

    int main(void)

    {

    //   1、GPIOA.0口输出   PA.8口输入

    GPIOA->CRL  = 0x03;     //50MHz推挽式输出

    GPIOA->CRH = 0x04;  //浮空输入

    //2、PA.0 == PA.8

    while(1)
    {

    if((GPIOA->IDR & 0x0100) == 0x0100)

         GPIOA->ODR = 0x01;

    else

         GPIOA->ODR = 0x00;

    }

    return (1);

    }

    三、

    &:与运算,隐藏,清零

    GPIOA->CRL & 0x01(起到隐藏作用,只与部分位进行运算)

    GPIOA->CRL & ~(0x01)  (起到对最低一位清零的作用)

    | :或运算,置一

    GPIOA->CRL  = GPIOA->CRL | 0x01(起到对最低一位置一的作用)

    GPIOA->CRH高八位输入控制低八位CRL输出

    //1、PA.0-PA.7    50MHz推挽输出     PA.8-PA.15浮空输入

    GPIOA->CRL = 0x33333333;

    GPIOA->CRH = 0x44444444;

    //2、输入状态反应到对应引脚的输出

    while(1)
    {
    if((GPIOA->IDR) & 0x0100) == 0x0100)  GPIOA->ODR = GPIOA->ODR | 0x01;
    else                                  GPIOA->ODR = GPIOA->ODR & (~0x01);
    if((GPIOA->IDR) & 0x0100) == 0x0200)  GPIOA->ODR = GPIOA->ODR | 0x02;
    else                                  GPIOA->ODR = GPIOA->ODR & (~0x02);
    if((GPIOA->IDR) & 0x0100) == 0x0400)  GPIOA->ODR = GPIOA->ODR | 0x04;
    else                                  GPIOA->ODR = GPIOA->ODR & (~0x04);
    if((GPIOA->IDR) & 0x0100) == 0x0800)  GPIOA->ODR = GPIOA->ODR | 0x08;
    else                                  GPIOA->ODR = GPIOA->ODR & (~0x08);
    if((GPIOA->IDR) & 0x0100) == 0x1000)  GPIOA->ODR = GPIOA->ODR | 0x01;
    else                                  GPIOA->ODR = GPIOA->ODR & (~0x10);
    if((GPIOA->IDR) & 0x0100) == 0x2000)  GPIOA->ODR = GPIOA->ODR | 0x01;
    else                                  GPIOA->ODR = GPIOA->ODR & (~0x20);
    if((GPIOA->IDR) & 0x0100) == 0x4000)  GPIOA->ODR = GPIOA->ODR | 0x01;
    else                                  GPIOA->ODR = GPIOA->ODR & (~0x40);
    if((GPIOA->IDR) & 0x0100) == 0x8000)  GPIOA->ODR = GPIOA->ODR | 0x01;
    else                                  GPIOA->ODR = GPIOA->ODR & (~0x80);
    
    }

    方法二:

    端口位设置/复位寄存器(GPIOx_BSRR)(x=A……E)

    端口复位寄存器(GPIOx_BRR)(x = A……E)

    GPIOA->BSRR = 0x01;

    GPIOA->BRR = 0x01;

    方法三:
    #define  PA1   GPIOA->BSRR

    #define  PA0   GPIOA->BRR

    PA1 = 0x01;

    PA0 = 0x01;

    根据硬件所提供的BSRR及BRR寄存器即可实现功能。

     

     

     

     

    展开全文
  • 调试寄存器原理

    千次阅读 2014-12-21 20:05:47
    (DRx对应任意的一个调试寄存器。LENn对应任意一个长度。Ln对应任意一个局部置位) DR0-DR7可以直接被读写操作(MOV 指令之类的,DRx可以是源操作数也可以是目的操作数)  但是,DRx的访问是需要
    下面介绍的知识性信息来自intel IA-32手册(可以在intel的开发手册或者官方网站查到),提示和补充来自学习调试器实现时的总结。
    希望能给你带去有用的信息。

    (DRx对应任意的一个调试寄存器。LENn对应任意一个长度。Ln对应任意一个局部置位)

    DR0-DR7可以直接被读写操作(MOV 指令之类的,DRx可以是源操作数也可以是目的操作数)

       但是,DRx的访问是需要一定权限的。比如你用MOV操作的话,你需要在实地址模式,系统管理模式(smm)或者在保护模式(CPL设0).如果权限不够,将会在访问DRx的时候尝产生#GP(general-protection)异常

    现在来看看DRx可以干些什么? 

    1.设置发生断点的地址(线性地址)
    2.设置断点的长度(1,2,4个字节,但是执行断点只能是1)
    3.设置在调试异常产生的地址执行的操作
    4.设置断点是否可用
    5.在调试异常产生时,调试条件是否是可用

    (以上直接翻译自"Intel 64 and IA-32 Architectures Software Developer’s Manual" volume 3。
    以下来自个人的总结。当然,也是参考intel官方资料得来的)

    我们来看看调试寄存器的一些细节信息。
    下图很重要,后面的介绍都是针对这个图说的。
    (当然不是我画的,是来自intel  ia-32系统结构开发手册18章2节)。

    点击图片以查看大图图片名称: DR0_DR7.jpg查看次数: 2307文件大小: 63.6 KB文件 ID : 39226

    调试寄存器 DR0-DR3
       这四个寄存器是用来设置 断点地址的。断点的比对在物理地址转换前(异常产生时,还没有将线性地址转换成物理地址)。由于只有0-3四个保存地址的寄存器,所以,硬件断点,在物理上最多只能有4个。
    调试寄存器DR4-DR5 
       这两个调试寄存器有CR4的DE标记控制。如果DE置位,那么对这两个寄存器的访问会导致#UD异常。如果DE置0,那么他们就被化名为DR6-DR7(你一定会问原来的DR6-DR7怎么办?这个…… 我也不知道。如果你搞明白了,一定记得告诉我)
    调试寄存器DR7(控制寄存器)
       (先介绍DR7对DR6的理解有好处。)

    DR7是调试控制寄存器。控制方式嘛!继续看:
    1.  L0-L3(由第0,2,4,6位控制):对应DR0-DR3,设置断点作用范围,如果被置位,那么将只对当前任务有效。每次异常后,Lx都被清零。
    2.  G0-G3(由第1,3,5,7位控制):对应DR0-DR3,如果置位,那么所有的任务都有效。每次异常后不会被清零。以确保对所有任务有效。但是,不知道为什么,我在测试时:
    设置Gn后,不能返回调试异常给调试器(如果你知道为什么,记得告诉我)
    3.  LE,GE(由第8,9位控制):这个在P6以下系列CPU上不被支持,在升级版的系列里面:如果被置位,那么cpu将会追踪精确的数据断点。LE是局部的,GE是全局的。(到底什么算精确的,我也不清楚,但是,我知道如果设置了这两个,cpu的速度会降低。我在测试中,都没有置位。)
    4.  GD(由第13位控制):如果置位,追踪下一条指令是否会访问调试寄存器。如果是,产生异常。在下面的DR6里面,你会知道他还和另外一个标志位有点关系。
    5.  R/W0-R/W3:(由第16,17,20,21,24,25,28,29位控制):这个东西的处理有两种情况。
    如果CR4的DE被置位,那么,他们按照下面的规则处理问题:
    00:执行断点
    01:数据写入断点
    10:I/0读写断点
    11:读写断点,读取指令不算
    如果DE置0,那么问题会这样处理:
    00:执行断点
    01:数据写入断点
    10:未定义
    11:数据读写断点,读取指令不算
    6.  LEN0-LEN3:(由第18.19.22.23.26.27.30位控制):指定内存操作的大小。
    00:1字节(执行断点只能是1字节长)
    01:2字节
    10:未定义或者是8字节(和cpu的系列有关系)
    11:4字节
    调试寄存器DR6(调试状态寄存器)
       这个寄存器主要是在调试异常产生后,报告产生调试异常的相关信息
    1.  B0-B3(DR0-DR3):DRx指定的断点在满足DR7指定的条件下,产生异常。那么Bx就置位。但是,有时,即使Ln和Gn置0,也可能产生Bx被置位。这种现象可能这样出现(提示:在p6系列处理器,REP MOVS在不断循环中产生的调试异常需要执行完了才能准确返回给调试进程):DR0的L0,G0都置0(DR0就是一个不能产生异常的断点了),然后在DR0指定的地址是一个REP指令的循环,这样,DR0就可能在这个循环之后的REP指令产生的调试异常中将B0置位
    2.  BD:BD需要DR7的GD置位,才有效。BD是在下一条指令要访问到某一个调试寄存器的时候,被置位的。
    3.  BS:单步执行模式时,被置位。单步执行是最高权限的调试异常。
    4.  BT:在任务切换的时候,被置位。但是必须在被切换去的任务的TSS段里面的T标记被置位的情况下才有效。在控制权被切换过去后,在执行指令前,返回调试异常。但是,需要注意,如果调试程序是一个任务,那么T标记的设置肯定就冲突了。然后,导致了死循环(BT的这些信息都是按照官方资料翻译而来,由于没有实际的操作,肯定会有理解上的出入。如果要深入的话,建议看官方资料)
      
    有些调试异常会将B0-B3清零。但是其他的DR6的位是不能被产生异常的进程清零的。每次调试异常返回后,调试进程都会先将DR6清零,再按照情况设置。以免产生不必要的错误。

    对齐问题和64位处理器
    对齐问题:
    这个问题是来源于LENn的设置,如果设置4字节,那么必须4字节对齐。例如:我们下4字节的断点,那么DRx需要是A0000/A0004/A0008这样的地址上。I/O地址是零扩展的(这个……也许意味着必须完全对齐)。因为,intel在比对地址时:用LENn的值去覆盖DRx里面保存的地址的低位。你可以想到,不对齐会有什么后果了吧。注意:执行断点只能是1字节。

    再用图片解释下(当然,图片来自intel官方资料):

    点击图片以查看大图图片名称: Align1.jpg查看次数: 2184文件大小: 68.6 KB文件 ID : 39224
    点击图片以查看大图图片名称: Align2.jpg查看次数: 2156文件大小: 33.1 KB文件 ID : 39225

    在64位处理器下:
    调试寄存器当然也是64位的。在操作过程中,写入,前面32位被置零。读取:只返回后32位。MOV DRx操作,前32位被忽略。
    DR6-DR7的高32位被保留。置零。如果置位,会产生#GP异常。8字节的读写断点完全被支持。

    最后,还是给个图片(64位处理器的布局):

    点击图片以查看大图图片名称: 64.jpg查看次数: 2170文件大小: 41.9 KB文件 ID : 39223

    最后需要提醒一个小问题:数据写入断点设置后。是在原数据被修改后,才产生调试异常。所以,返回异常时,原有数据已经被修改。如果想保留原有数据,需要自己提前保存对应地址的数据。


    展开全文
  • STM32 F429 USART发送寄存器原理及TXE,TC中断的使用 先来看USART 字符发送的基本步骤 : 字符发送步骤 1.向USART_CR1的 UE 位写1,enable USART 2.对USART_CR1的 M 位编程定义字长 3.对USART_CR2中停止位stop 数量...
  • LUT查找表实现移位寄存器原理精讲

    千次阅读 2020-02-15 16:01:36
    在文章《LUT是如何实现千万种逻辑结构的》里面我们讲过了LUT的原理,实现逻辑函数时,相当于一个ROM将结果预存,然后把通过输入信号当作地址对预存的结果进行寻址。因此同样借助LUT加几个端口,就可以实现RAM。...
  • 1 串转并功能,通过移位寄存器和输出锁存器实现 2 FPGA需要通过74HC595这个芯片把16位的数据(sel+seg)变为并行端口用来驱动数码管 3 3.3V供电情况下,取SHCP时钟频率位12.5MHz(50-20ns,25-40ns,12.5-80ns),让...
  • mmap(NULL, 4194304, PROT_READ, MAP_SHARED, 3, 0x38017e800000) = 0x7ffff62a9000
  • 真的是在实模式下用段寄存器左移4位与偏移量相加,还是在保护模式下用段描述符中的基地址加偏移量,难道两者是毫无关联的吗?    答案是两者其实是一样的。当 Intel 把 80286 推出时,其地址空间变成了 24 位,...
  • (DRx对应任意的一个调试寄存器。LENn对应任意一个长度。Ln对应任意一个局部置位) DR0-DR7可以直接被读写操作(MOV 指令之类的,DRx可以是源操作数也可以是目的操作数)  但是,DRx的访问是需要
  • 移位寄存器原理

    2021-01-20 00:39:19
    移位寄存器原理  移位寄存器不仅能寄存数据,而且在时钟信号的用下使它其中的数据依次左移或者右移。  四位移位寄存器原理:F0、F1、F2、F3是四个边沿触发的触发器D,每一个触发器的输出端Q接到右边一个...
  • 本文主要对移位寄存器工作原理及其应用进行了说明,一起来学习一下
  • 微机原理寄存器

    2021-06-10 21:18:56
    一、寄存器 1.通用寄存器名称 1+.寄存器分身 2+.数据寄存器作用 3+.地址指针寄存器作用 4+.变址寄存器作用 5+.BI,BP对比 2.控制寄存器 1+.运行流程 2+.状态标志位 3+.控制标志位 3.段寄存器
  • 我们已知单片机的内部有ROM、有RAM、有并行I/O口,那么,除了这些东西之外,单片机内部究竟还有些什么,这些个零碎的东西怎么连在一起的,让我们来对单片机内部的寄存器作一个完整的功能分析吧!
  • 3.6.5.使用结构体方式访问寄存器原理 (1)C语言访问寄存器的本质是C语言访问内存,本质思路是:定义一个指针(临时变量)指向这块内存,然后*p = xx这种方式去解引用指针从而向目标内存中写入内容。 (2)缺陷:当...
  • 寄存器的基本原理

    千次阅读 2020-01-22 09:56:41
    CPU中有很多的寄存器,有临时保存数据的通用寄存器,也有专门保存指令编码或者指令地址的寄存器。它们都有存储信息的能力。 那在这一节,我们就来分析这些寄存器是如何实现的。 在CPU当中用来存放信息的非常重要的...
  • 移位寄存器的工作原理,详细说明,原理
  • 4.3 寄存器的基本原理

    2019-09-20 21:01:51
    4.3 寄存器的基本原理 CPU中有很多的寄存器,有临时保存数据的通用寄存器,也有专门保存指令编码或者指令地址的寄存器。它们都有存储信息的能力。 那在这一节,我们就来分析这些寄存器是如何实现的。 在CPU当中...
  • 导读: 我们已知单片机的内部有ROM、有RAM、有并行I/O口,那么,除了这些东西之外,单片机内部究竟还有些什么,这些个零碎的东西怎么连在一起的,让我们来对单片机内部的寄存器作一个完整的功能分析吧!
  • 在进行复杂模型机设计时,我有一个一直困扰我的问题,那就是273这个寄存器(乃至其他所有寄存器)的工作原理是什么?他们是怎么寄存的?如果不弄清楚的话,数据寄存器的读写会发生错误,并且我对数据的产生流程会...
  • 寄存器

    2020-12-18 13:03:51
    1. 寄存器 集成8位寄存器【74HC/HCT374】 功能表 2. 移位寄存器 (1) 基本的移位寄存器 (2) 多功能双向移位寄存器 工作原理 典型的多功能4位双向移位寄存器
  • 一、移位寄存器工作原理及代码分析(以MAX7219芯片为例) 首先要明白DIN管脚的含义,其为串行数据输入端口,在时钟上升沿时数据被载入内部的 16 位寄存器。 而CLK即为时钟序列输入端,所以当要输入数据时,先得把...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,491
精华内容 2,996
关键字:

寄存器原理