;Print 361375661375661# Mod 1
;FLD src 装入实数到st(0)
004019E3 DD05 80104000 fld qword ptr [401080] ;ds:[00401080]=361375661375661.0
004019E9 83C4 0C add esp, 0C ;+OC,MSVBVM60.__vbaFpI4需要临时变量空间
004019EC FF15 64104000 call [<&MSVBVM60.__vbaFpI4>] ; MSVBVM60.__vbaFpI4
004019F2 6A 00 push 0
004019F4 56 push esi
004019F5 68 B8144000 push 004014B8
004019FA FFD7 call edi ; 调用显示命令
;竟然没有计算过程................
; MSVBVM60.__vbaFpI4,好像只负责取整,好吧
4FFA6C70 > D9FC frndint ;保存实数st(0)到dest
4FFA6C72 83EC 0C sub esp, 0C ;这里减了0C,恢复到栈指针
4FFA6C75 DB1424 fist dword ptr [esp] ;舍入到整数
4FFA6C78 DF7C24 04 fistp qword ptr [esp+4] ;然后再执行一次出栈操作,跳了4字节
4FFA6C7C DFE0 fstsw ax ;保存状态字的值到AX
4FFA6C7E A8 0D test al, 0D ;测试是否超栈顶,会写状态位
4FFA6C80 0F85 40B30000 jnz 4FFB1FC6 ;上步检测到错误,这里应该是溢出,没跟踪
4FFA6C86 58 pop eax
4FFA6C87 83C4 08 add esp, 8 ;其余8字节。用于防止数据超栈顶导致错误
4FFA6C8A C3 retn
;那就再来一段 Print 361375661375661# Mod 3
004019E3 DD05 80104000 fld qword ptr [401080]
004019E9 83C4 0C add esp, 0C
004019EC FF15 64104000 call [<&MSVBVM60.__vbaFpI4>] ; MSVBVM60.__vbaFpI4
004019F2 99 cdq ; 扩展EAX寄存器为EDX:EAX,64位,为除法做准备
004019F3 B9 03000000 mov ecx, 3 ; MOD 3 的 3,用的是 32位寄存器
004019F8 F7F9 idiv ecx ; edx:eax 除以 ecx。
;如果参数是 r8/m8, 将把 AX 做被除数; 商 -> AL, 余数 -> AH
;如果参数是 r16/m16, 将把 DX:AX 做被除数; 商 -> AX, 余数 -> DX
;如果参数是 r32/m32, 将把 EDX:EAX 做被除数; 商 -> EAX, 余数 -> EDX
004019FA 52 push edx ; 调用显示命令
到这里,真相大白了,需要使用 idiv 有符号整数除法时 , 就一定会换算成整数,这个处理过程在 __vbaFpI4 (浮点转整数4字节)函数中处理
然而这个 __vbaFpI4 函数中使用 4字节来保存数据 [esp+4] ,如果超了 LONG范围(-2,147,483,648 到 2,147,483,647),自然而然的就报溢了错误了。
经测试 ,mod
和 \ 会报这个错误,猜测就是会调用 idiv 指令。
好奇怪, / 竟然不报错。。。。继续看
;'Print 361375661375661# / 3
004019D3 DD05 80104000 fld qword ptr [401080] ;同样,装入数据
004019D9 833D 00204000 0>cmp dword ptr [402000], 0 ;以及下一句,检测错误用的
004019E0 75 08 jnz short 004019EA
004019E2 DC35 78104000 fdiv qword ptr [401078] ;调用浮点除,[401078]=3,好吧服了
以用反汇编使用 OllyICE看的
工程:
窗体上拉一个命令命令,双击后然后输入以下二条命令
Print "HYHYHY"
'用于反汇编里定位指令位置
Print 361375661375661# / 3
'这行命令根据需要修改
--------------------
解决办法:自己整大数 除法去吧。
[此贴子已经被作者于2022-12-19 20:33编辑过]