C 从整数中减去0x8000

C 从整数中减去0x8000,c,C,我在反向工程一些旧的C,在Win95下运行(是的,在生产中)似乎是用Borland编译器编译的(我没有工具链) 有一个函数(除其他外)执行以下操作: static void unknown(int *value) { int v = *value; v-=0x8000; *value = v; } 我不太明白这是怎么回事。我假设这个上下文中的int是有符号的32位。我认为0x8000应该是无符号32位int,并且超出有符号32位int的范围。(编辑-这是错误的,它超出了有符号16位

我在反向工程一些旧的C,在Win95下运行(是的,在生产中)似乎是用Borland编译器编译的(我没有工具链)

有一个函数(除其他外)执行以下操作:

static void unknown(int *value)
{
  int v = *value;
  v-=0x8000;
  *value = v;
}
我不太明白这是怎么回事。我假设这个上下文中的int是有符号的32位。我认为0x8000应该是无符号32位int,并且超出有符号32位int的范围。(编辑-这是错误的,它超出了有符号16位int)

我不确定其中一个是否会首先被施放,以及施放将如何处理溢出,和/或减法将如何处理溢出

我可以尝试一个现代系统,但我也不确定结果是否相同

为清晰起见,请编辑:

1:'v-=0x8000;'直接来自原始代码,这对我来说没有什么意义。v被定义为int

2:我有密码,这不是asm的

3:原来的代码非常非常差

编辑:我有答案!下面的答案不太正确,但它让我明白了(修复后,我会将其标记为答案)

v中的数据来自一个不明确的源,它实际上似乎在发送无符号16位数据,但它被存储为有符号整数。在程序中,后一种情况下,所有值都被转换为浮点数,并归一化为平均0点,因此实际值无关紧要,只是顺序而已。由于我们将无符号int视为有符号int,因此32767以上的值被错误地放置在0以下,因此此黑客将该值保留为有符号,但将负数和正数交换(不改变顺序)。最终的结果是,所有数字的顺序都相同(但值不同),就好像它们最初是无符号的一样


(……这不是这个程序中最坏的代码例子)

这个页面可能有线索- Borland C++ 2。x(带Turbo C)

不存在负数值常量。如果 负号位于数字常量之前,它被视为 一元负号运算符,与常量一起, 构成一个数值表达式。这对我们来说很重要 -32768,虽然它可以表示为int, 实际上有long int类型,因为32768有long类型。到 要获得所需的结果,可以使用(int)-32768, 0x8000或0177777

这意味着对负数使用。有趣的是,两个0x8000的补码是0x8000本身(因为值+32768不适合有符号2字节整数的范围)

那么这对你的函数意味着什么呢?就位而言,这具有切换符号位的效果,以下是一些示例:

f(0) = f(0x0000) = 0x8000 = -32768
f(1) = f(0x0001) = 0x8001 = -32767
f(0x8000) = 0
f(0x7fff) = 0xffff

这似乎可以表示为“代码> Val^=0x8000”/CODE,但XOR运算符可能不是在Borland中实现的吗?

< P>,可能有一个线索在这个页面上——Borland C++ 2。x(带Turbo C)

的指南。 不存在负数值常量。如果 负号位于数字常量之前,它被视为 一元负号运算符,与常量一起, 构成一个数值表达式。这对我们来说很重要 -32768,虽然它可以表示为int, 实际上有long int类型,因为32768有long类型。到 要获得所需的结果,可以使用(int)-32768, 0x8000或0177777

这意味着对负数使用。有趣的是,两个0x8000的补码是0x8000本身(因为值+32768不适合有符号2字节整数的范围)

那么这对你的函数意味着什么呢?就位而言,这具有切换符号位的效果,以下是一些示例:

f(0) = f(0x0000) = 0x8000 = -32768
f(1) = f(0x0001) = 0x8001 = -32767
f(0x8000) = 0
f(0x7fff) = 0xffff

这似乎可以表示为
val^=0x8000
,但也许当时Borland没有实现XOR运算符?

在Borland C 3.x中,
int
short
是相同的:16位<代码>长为32位

十六进制文字具有第一种可以表示值的类型:
int
unsigned int
long int
unsigned long int

在Borland C的情况下,
0x8000
是一个32768的十进制值,不适用于
int
,但适用于
无符号int
。所以
unsigned int
就是这样

语句
v-=0x8000
v=v-0x8000相同

在右侧,将
int
v
隐式转换为
无符号int
,根据规则执行算术运算,生成一个
rval
,即
无符号int
。然后,根据规则,
unsigned int
被隐式地转换回
lval
的类型


因此,据我估计,最终的效果是切换符号位——这可以通过简单的位旋转更容易、更清晰地完成:
*value^=0x8000int
short
是相同的:16位<代码>长
为32位

十六进制文字具有第一种可以表示值的类型:
int
unsigned int
long int
unsigned long int

在Borland C的情况下,
0x8000
是一个32768的十进制值,不适用于
int
,但适用于
无符号int
。所以
unsigned int
就是这样

语句
v-=0x8000
v=v-0x8000相同

在右侧,将
int
v
隐式转换为
无符号int
,根据规则执行算术运算,生成
rval<