中断不够用了

郁闷阿
 
计算机主板中断已经不够用了
刚装上的USB2.0控制卡只能开一个控制器,开另外一个的话和显卡抢中断必定死机
如果把它放在声卡旁边这老大还不肯工作!
 
目前机器里面卡是这么插的,找时间研究一下有没有优化的余地:
 
GF FX 5600XT AGP
NEC USB2.0
VOODOO 2
8139
8139
——–
SB Live
 
 记下一些资料,日后使用:中断级别 通常用途 说明
0 时钟  
1 键盘  
2 与IRQ 9级连  
3 COM2或COM4  
4 COM1或COM3  
5 LPT2 因为许多用户没有第二个并行口,因此它常常空闲,声卡可以使用此中断
6 软盘控制器  
7 LPT1 声卡可以使用此中断
8 实时时钟  
9 与IRQ 2级连 直接与2相连,有时通知软件9时意味着2
10 未使用 通常用于网卡
11 未使用 由SCSI控制器使用
12 PS/2,总线鼠标 如果用户没有PS/2或总线鼠标,此中断空闲
13 协处理器 通知CPU协处理器错误
14 硬盘控制器 如果用户未使用IDE硬盘,可以将它用于其它设备
15 有些计算机将此中断分配为第二个IDE控制器 I如果用户未使用第二个IDE硬盘控制器,可以将它用于其它设备
按理说现在的主板都有APIC,为啥没有打开呢!?研究研究……

如何编写 Visual C++ 的表达式分析插件

Visual C++ 为我们提供了强大易用的调试环境,特别是对于简单数据类型和常见的类类型可以在调试的时候直接看到变量的值。然而这种方便是有局限性的,如果我们定义了一个复杂的数据类型,则在调试器中就很有可能看不到我们需要的信息。举个简单的例子,对于FILETIME这种类型来说:
typedef struct STRUCT tagFILETIME {
    DWORD dwLowDateTime;
    DWORD dwHighDateTime;
} FILETIME;
显然在调试器中我们无法直接看到常规格式的日期。再来一个更极端的例子:
如果我们在代码里面用 DWORD id 来表示一个文件的索引,每个id对应一个文件名,而且我们希望在调试的时候直接看到id对应的文件名该怎么办?显然,Visual C++ 调试器对此无能为力。但是!我没有说“完全”无能为力,微软在 Visual C++ 调试器中支持用户自定义表达式分析扩展!
这究竟是怎么实现的呢?原来,通过正确注册自定义数据类型分析求值函数之后,Visual C++ 调试器会在表达式求值的时候调用用户自定义的求值函数。
下面我就举一个简单的例子来说明如何编写 Visual C++ 的表达式分析插件。
1 新建一个标准dll工程
起名字叫做MyAddin
2 在MyAddin.def文件中写
EXPORTS
    AddIn_MyID2STRING
3 在MyAddin.h文件中写
extern "C" ADDIN_API
HRESULT WINAPI
AddIn_ID2STRING(DWORD, DEBUGHELPER*, int, BOOL, char*, size_t, DWORD);
4 新建一个vsaddin.h文件,写入
#ifndef VSADDIN_H
#define VSADDIN_H
#include <windows.h>
typedef struct tagDEBUGHELPER
{
    DWORD dwVersion;
    BOOL (WINAPI *ReadDebuggeeMemory)(struct tagDEBUGHELPER *pThis,
                                      DWORD dwAddr,
                                      DWORD nWant,
                                      VOID* pWhere,
                                      DWORD *nGot);
    // from here only when dwVersion >= 0x20000
    DWORDLONG (WINAPI *GetRealAddress)(struct tagDEBUGHELPER *pThis);
    BOOL (WINAPI *ReadDebuggeeMemoryEx)(struct tagDEBUGHELPER *pThis,
                                        DWORDLONG qwAddr,
                                        DWORD nWant,
                                        VOID* pWhere,
                                        DWORD *nGot);
    int (WINAPI *GetProcessorType)(struct tagDEBUGHELPER *pThis);
} DEBUGHELPER;
typedef HRESULT (WINAPI *CUSTOMVIEWER)(DWORD dwAddress,
                                       DEBUGHELPER *pHelper,
                                       int nBase,
                                       BOOL bUniStrings,
                                       char *pResult,
                                       size_t max,
                                       DWORD reserved);
#endif /* VSADDIN_H */
5 在MyAddin.cpp中写
#include "vsaddin.h"
#include "MyAddin.h"
class ID2STRING
{
public:
 DWORD ID;
};
char* ID_List[10] = {"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
static bool
BridgeObject(DEBUGHELPER* pHelper, void* realAddress,
       ID2STRING* stringObject)
{
 if (false == GetMemory(pHelper, realAddress, sizeof(ID2STRING), stringObject))
 {
  OutputDebugString("GetMemory Error A");
  return false;
 }
 return true;
}
HRESULT WINAPI
AddIn_MyID2STRING(DWORD dwAddress, DEBUGHELPER* pHelper,
    int /*nBase*/, BOOL /*bUniStrings*/,
    char* pResult, size_t max,
    DWORD /*reserved*/)
{
 *pResult = ”;
 __try
 {
  // We can’t use a stack allocated ID2STRING here due to the use of SEH
  char stringBuffer[sizeof(ID2STRING)];
  ID2STRING* Id2String = (ID2STRING*)stringBuffer;
  void* realAddress = GetRealAddress(pHelper, dwAddress);
  if (false == BridgeObject(pHelper, realAddress, Id2String))
  {
   OutputDebugString("BridgeObject Error");
   return E_FAIL;
  }
  
  snprintf(pResult, max, "%s", ID_List[Id2String->ID]);
 }
 __except(EXCEPTION_EXECUTE_HANDLER)
 {
  OutputDebugString("EXCEPTION_EXECUTE_HANDLER");
  return E_FAIL;
 }
 return S_OK;
}
OK,代码部分就是这样了,编译即可
6 把编译好的 MyAddin.dll 放到Visual Studio 安装路径的 Common7IDE 和 Common7PackagesDebugger 下(这个MSDN中写的有错,我的经验是两个目录里都放一份,或者看下面的说明)
7 用文本编辑器打开 Common7PackagesDebugger 目录下的 autoexp.dat,找到
; see EEAddIn sample for how to use these
;_SYSTEMTIME=$ADDIN(EEAddIn.dll,AddIn_SystemTime)
;_FILETIME=$ADDIN(EEAddIn.dll,AddIn_FileTime)
在下面添加一行:
ID2STRING=$ADDIN(MyAddin.dll,AddIn_MyID2STRING)
当然,这里可以写绝对路径,那么就不用按照步骤6里面说得那样放置文件了。而且,在修改这个文件的介绍上,MSDN写错了,写的时候要小心。
好,完工!
我们新建一个工程,在里面使用
class ID2STRING
{
public:
 DWORD ID;
};
调试的时候看到的ID就是
char* ID_List[10] = {"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine"};
的内容了
当然,我在代码里面没有做下标越界的处理,这仅仅是一个例子而已
注意事项:我在代码中使用了SEH,这是因为如果没有正确处理异常,插件将导致 Visual Studio IDE 崩溃。

Visual Studio 插件

因为工作上的需要,最近一直在看如何编写 Visual Studio 插件
 
===================割就割==================
 
常见的 Visual Studio 插件有两种,一种可以称之为功能扩展插件,一种可以称之为环境扩展插件
 
功能扩展插件:这个最广泛的用途就是扩展调试器的表达式求值,例如自定义的类,VC调试器不知道如何在调试的时候正确显示它的内容,例如数据成员,于是我们就可以通过写一个调试器功能扩展插件完成这个操作。在MSDN中可以找到一个例子,很简单,写一个DLL,导出一个函数就OK。
 
 
环境扩展插件:这个可以说是 Visual Studio 最恐怖的地方,一切的一切都可以用这个方法扩展!其实Visual Studio 本身只是一个壳,VC,VB,VC#都是这个壳的插件而已。理论上通过编写这种插件,我们可以实现自己的语言、编译器、调试器、建模工具等等插件来集成到 Visual Studio,而看起来就好像原本就是 Visual Studio 自带的一样。

编写这种插件需要 VSIP SDK,这个SDK是不包括在MSDN订阅中的,需要在微软注册并且下载,或者订购相关DVD(貌似免费!?),有兴趣的朋友可以试试看。