放假回到家里, 在我家中的机器上跑风魂写的程序时, 发现了许多问题, 由于我家中的机器是 5x86 自然不支持 MMX, 所以马上可以断定问题出在从前调试不充分的非 MMX 版本的某个函数上.

可是当问题逐步定位到出问题的 RLE 精灵的绘制上, 反复阅读程序却发现不了问题的所在 :-( 直到我生成机器码后才发现, 产生问题的是 ALIGN 这个伪代码.

为了提高代码的运行效率, 在最关键的循环跳转处我都做了 代码对齐的操作(最近我发现这个对 P II 的 CPU 没有效果) 大量使用了 "ALIGN 4". 我原来以为, VC 将插入 NOP 来对齐代码, 结果发现, 为了提高效率, VC 按情况填入了单字节,双字节, 三字节指令做空操作, 使空操作的时间最短. 当需要插入 1 字节时, 理所当然的插入一个 0x90 (NOP); 需要插入 2 字节时则是 0x8b 0xff (MOV DI,DI) 这也无可厚非, 此指令不破坏任何寄存器, 也不影响标志位; 可需要填入 3 个字节的时候, 我用的 VC6 却令人费解的填入了 0x8d 0x49 0x00 (LEA CX,[BX+DI+00]), 很明显它影响了 CX, 而风魂的代码就是受到了它的影响.

这个问题困扰了我一个晚上, 哪位朋友如果能告诉在下一解决方案, 万分感激.

云风 草书于1999.8.1


云风 8.2 补充

经过网友老狼在流言板 上的提示, VC 在处理 ALIGN 本身时并无问题, 0x8d 0x49 0x00 正确的汇编代码是 LEA ECX,[ECX] . 前天我用的 debug 中的反汇编, 不支持 32bit asm 所以搞错了. 但是程序死机的问题依然存在, 所以今天我花时间阅读了代码生成的机器码, 果然发现了真正的问题所在, 这是 VC 在处理 ALIGN 的一个 Bug.

在我的程序里有一处条件跳转, X86 的汇编中, 相对短距跳转的范围是 -128 ~ 127. 我的代码中这段程序跳转的距离为 -129, 而 VC 依然使用了 短跳转, 所以 -129 被用一个字节错误的表示, 成了 0x7f (127) 这么弱智的 BUG 是怎么出现的呢, 在于其间有一条 ALIGN 伪代码. 这条指令会产生不定长的几个字节, 愚蠢的 VC 没有将它产生的代码统计在内, 所以导致了短跳转越界的问题 :-( 如果你不太明白我说的问题, 请看看这个简单的程序, 请用 VC 编译一下, 能得到意想不到的结果.

Sigh, 一直对 VC 的印象不是很好, 看来要响应网友的号召改用性能, 界面能非常棒的 BC 了.