Dav*_*son 2 assembly intel machine-code cpu-registers
我正在用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
Run Code Online (Sandbox Code Playgroud)
机器代码将上述内容翻译成:
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
Run Code Online (Sandbox Code Playgroud)
我在Windows计算器中键入了十六进制24并将其切换为二进制.结果是00100100.这似乎是两个虚拟位,然后是ESP寄存器两次.
任何人都可以解释为什么会这样吗?我认为这超出了MS C++编译器的奇怪怪癖,直接进入了70年代或80年代(90年代?)的遗留功能领域,但我找不到任何在线参考资料,为什么这ESP是一个例外mov操作的味道.谢谢!
[esp]不能modr/m仅使用字节编码,它需要一个SIB字节.请参阅表2-2.在intel指令集参考中使用ModR/M字节的32位寻址表.44modr/m 的值对另一个操作数进行编码,并且后跟eax一个SIB字节和一个位移字节.编码SIB值,见表2-3.带有SIB字节的32位寻址表.24[esp]
该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
Run Code Online (Sandbox Code Playgroud)
这本身不应该导致您的崩溃,而是随机尝试覆盖内存中的内容.