我正在对MSVC ++中的机器代码进行一些实验,并创建了一个函数,该函数使我可以围绕带符号位移的寄存器构建mov操作。一切进行顺利,直到我的功能得以建立mov [esp-4], eax
。突然,我的程序开始崩溃。在进行拆卸后,我发现了一些很奇怪的东西。对于此mov
从ESP
寄存器偏移引用的操作,在参数字节和有符号位移之间放置了一个附加字节。该字节似乎总是为0x24。因此出于好奇,我分解了以下代码__asm
块并获得了一些有趣的结果:
mov [eax - 4], eax
mov [ecx - 4], eax
mov [edx - 4], eax
mov [ebx - 4], eax
mov [esp - 4], eax
mov [ebp - 4], eax
mov [esi - 4], eax
mov [edi - 4], eax
机器代码将以上内容翻译为:
89 40 FC
89 41 FC
89 42 FC
89 43 FC
89 44 24 FC <--- WAT!
89 45 FC
89 46 FC
89 47 FC
我在Windows计算器中键入了十六进制24,并将其切换为二进制。结果是00100100
。这似乎是两个虚拟位,然后是ESP
寄存器两次。
谁能阐明为什么会这样?我认为这超出了MS C ++编译器的怪异之处,并且直接进入了70年代或80年代(90年代?)的遗留功能领域,但是我找不到关于为什么ESP
例外的在线参考资料mov
操作风格。谢谢!
[esp]
不能modr/m
仅使用字节进行编码,它需要一个SIB
字节。请参阅表2-2。intel指令集参考中带有ModR / M字节的32位寻址形式。44
modr / m的值编码为另一个操作数,eax
然后是一个SIB
字节和一个位移字节。SIB
的值24
进行编码[esp]
,见表2-3。具有SIB字节的32位寻址形式。
该SIB
可编码所有其他变种太多,但因为这是1个字节长,汇编器不使用的形式。这是供参考的列表:
89 44 20 FC mov [eax-0x4],eax
89 44 21 FC mov [ecx-0x4],eax
89 44 22 FC mov [edx-0x4],eax
89 44 23 FC mov [ebx-0x4],eax
89 44 24 FC mov [esp-0x4],eax
89 44 25 FC mov [ebp-0x4],eax
89 44 26 FC mov [esi-0x4],eax
89 44 27 FC mov [edi-0x4],eax
就其本身而言,这不应该导致崩溃,但可能会随机尝试覆盖内存中的内容。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句