gpt4 book ai didi

vb6 - VB6 中计算负数 Mod 为 2 的幂的数时的奇怪行为

转载 作者:行者123 更新时间:2023-12-04 15:38:26 27 4
gpt4 key购买 nike

我正在调试一段用 VB6 开发的旧代码,发现了一些非常奇怪的东西。可以使用以下简单代码进行演示:

Private Sub Command1_Click()
Dim a As Integer
Dim b As Integer
Dim c As Integer

a = 0
Text1.Text = a - 1
Text2.Text = CStr((a - 1) Mod 4)

b = 0
b = b - 1
Text3.Text = b
Text4.Text = CStr(b Mod 4)

c = 0 - 1
Text5.Text = c
Text6.Text = CStr(c Mod 4)

End Sub

这是表格的样子:

enter image description here

您会认为在单击按钮后 Text2、Text4 和 Text6 应该显示相同的内容,即 -1。当我按 F5 在 IDE 中运行它时就是这种情况。

这是我在 IDE 中运行时的样子:

enter image description here

当我从 IDE 制作一个 exe 并运行 exe 本身时,发生了奇怪的事情。 Text1 和 Text6 显示 -1,但 Text4 显示 3。

这是我在 IDE 之外运行 exe 时的样子:

enter image description here

仅当第二个操作数是 2 的幂时才会发生这种情况。当我将 4 更改为 5 时,所有文本框都显示 -1。

我在 2 台 Windows 10 机器上对此进行了测试,并得到了相同的结果。

我知道 VB6 已经过时了,现在没有多少人仍然可以使用它进行测试。如果有人能帮助我理解这一点,我将不胜感激。

谢谢。

最佳答案

这似乎是一个编译器错误。在 Integer 的情况下,编译器无法识别该值是有符号的。 (16 位值),但是 doesLong 的情况下尊重它.

执行模 4 的代码在每种情况下几乎相同,并遵循 optimized pattern for modulo powers of 2 :

长(b Mod 4&):

or   eax, 0xFFFFFFFF  # eax = 0xFFFFFFFF (which is -1)
and eax, 0x80000003 # eax = 0x80000003 The modulo op, note it's signed because of the 8

jns other_code # Skip the next three lines if the result is non-negative (it isn't here)

dec eax # eax = 0x80000002
or eax, 0xFFFFFFFC # eax = 0xFFFFFFFE
inc eax # eax = 0xFFFFFFFF (which is -1)

other_code:

到底 eax包含0xFFFFFFFF,即-1,传递给显示。

整数( b Mod 4 ):

or   eax, 0xFFFFFFFF  # eax = 0xFFFFFFFF, ax = 0xFFFF (which is -1 in both cases)
and ax, 0x3 # eax = 0xFFFF0003, ax = 0x0003. Should have been "and ax, 0x8003!"

jns other_code # Skip the next three lines if the result is non-negative (it incorrectly is)

dec ax # Skipped
or ax, 0xFFFC # Skipped
inc ax # Skipped

other_code:

到底 eax包含 0xFFFF0003 然后传递给 __vbaStrI2显然会忽略两个高字节并仅使用 0003 的函数.

and ax, 0x8003被用来代替 and ax, 0x3 ,然后跳过的行将触发并转换 0xFFFF0003进入 0xFFFFFFFF ,即 -1。

禁用优化后,按位模数学被一个简单的除法取代:

sub   ax, 0x1          # b = b - 1
mov cx, 0x4 # Prepare division by 4
idiv cx # Integer division

至于为什么会为 ac按预期工作,这是因为编译器计算 -1 Mod 4在编译阶段并将结果硬编码到可执行文件中:

push  0xFFFFFFFF       # Pass hardcoded -1 for display

other_code:

从技术上讲,在 b 的情况下,没有什么可以阻止它做同样的事情。 ,因为它也可以证明被除的值是 -1 .我无法确定它为什么不这样做 - 也许它过早地停止了静态分析一步,或者可能是编写 -1 的结果代码。回到 b的内存地址它认为效率会较低。

关于vb6 - VB6 中计算负数 Mod 为 2 的幂的数时的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58663568/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com