MinGW: Minimalist GNU for Windows,是GNU开发环境在Windows下的一个移植。而MSYS则是与MinGW配套的一个shell环境以及相关的工具程序。
阅读全文 »我的开发环境是 MIPS_4ke,调试器是 Multi 2000 v4 + SlingShot + EJTAG。
昨天在调试程序的时候调试到这样一段程序:
UI8 * pDest = g_pStreamBuffer;
if (*(UI32*)pDest != 0x000001BE) {
return;
}
pDest += 10;
if (*(UI32*)pDest != 0x000001B5) {
return;
}
调试器跟踪到第二个 *(UI32*)pDest 时发生错误,调试器拒绝继续调试。开始百思不得其解,因为第一个*(UI32*)pDest正常地得到了所需要的结果。后来想明白,原来是对齐的问题。MIPS从内存中读取一个UI32时必须在4字节边界开始读取,而上面的操作执行了 pDest += 10之后,pDest就不再位于4字节的边界上,因此执行第二个 *(UI32*)pDest访问时发生了CPU异常。于是我做了下面的这个函数:
UI32 getUI32(UI8 * pSrc)
{
return (
(((UI32)(* pSrc )) << 24) |
(((UI32)(*(pSrc+1))) << 16) |
(((UI32)(*(pSrc+2))) << 8) |
(((UI32)(*(pSrc+3))) )
);
}
这样就能够从任意地址读取四个字节了。
另外,Multi的编译器指令中有一个 pack 指令,该指令能够指定定义结构时的最小的对齐字节数。例如正常情况下进行下列定义时,各个成员所占定义如下所示:
typedef struct {
UI32 a; // 4 bytes
UI8 b; // 1 byte + 3 bytes padding
UI32 c; // 4 bytes
}
由于第三个成员 c 为 UI32,CPU在读取c时需要在4字节边界上对齐,因此成员b后面就留下了三个padding字节。如果这样写即可避免该问题。
#pragma pack(1)
typedef struct {
UI32 a; // 4 bytes
UI8 b; // 1 byte
UI32 c; // 4 bytes
}
#pragma pack()
但是这样一来,CPU读取c的时候为什么不会产生异常?其实编译器作了特殊的处理,它将读取c的指令分解成两条,第一条在前一个边界上读取c的前三个字节,第二条在后一个边界上读取c的最后一个字节,因此不会产生异常。
前一阵子遇到的一个问题是,如何在Java程序中调用Windows DLL的函数。查了查资料,得知使用名为JNI(Java Native Interface)的方式可以让Java调用DLL中的函数。JNI的使用方法如下:
- 在Java中定义JNI调用,并撰写使用该JNI调用的相关代码。
- 根据定义好的JNI调用生成相应的C语言头文件。
- 利用上一步生成的头文件,使用C书写Windows平台上的代码。
- 编译C代码生成DLL库文件。
- 执行Java程序中JNI调用的代码。
本文总结了Java中很容易误解的一些知识点。
阅读全文 »
昨天在讨论文档中的某个函数的实现方法的问题,我提议把某个循环计数变量unsigned int改成int,以便使用负值来表示出错信息。结果被人指出,改成int会影响代码效率,因为对这个变量有如下的操作:a = (a+1)%64,如果a为unsigned型,那么编译器会自动进行优化,而对于int型则不会。后来验证了一下果然如此。
阅读全文 »Windows下最基本的窗口程序。
阅读全文 »
