【发布时间】:2016-11-10 05:57:47
【问题描述】:
作为组装新手,我使用 gcc 进行逆向工程。但现在我遇到了一个奇怪的问题:我尝试将两个 64 位整数相乘以得到 x86-64。 C - 代码如下所示:
unsigned long long
val(unsigned long long a, unsigned long long b){
return a*b;
}
并用 gcc 编译:
val:
movq %rdi, %rax
imulq %rsi, %rax
ret
对无符号整数使用有符号乘法可能违反直觉,但它适用于 C。
但是,我想检查乘法是否溢出。现在,如果结果大于2^63-1,则设置溢出标志(我猜是因为它毕竟是有符号乘法)。但对于无符号 64 位,只要结果不大于 2^64-1,这仍然可以。
在这种情况下,做乘法(在汇编中)的正确方法是什么?
【问题讨论】:
-
您能否事后进行测试,看看结果是否比以前“(unsigned ...) 小”?只是猜测......
-
或者,您可以简单地使用
mul,如果无符号乘法的结果溢出操作数大小,它将设置 CF 和 OF。 -
@ead:因为
imul对n*n -> n位乘法执行相同的操作。此外,mul只有一个操作数形式(它隐式使用[r/e]ax)并且总是破坏[r/e]ax和[r/e]dx。它只是不太灵活。 -
在 C 中,无符号乘法不会溢出。如果结果超出无符号类型的范围,则通过实际上丢弃高位进行调整。如果您想检查是否有必要进行任何此类调整,那么您正在做的不是 C 无符号乘法。 (我绝对不是暗示这有什么问题。)
-
@KeithThompson:“溢出”在这里被用来表示“环绕”,例如丢弃的高半部分是否非零。它是至少具有一种技术含义的词之一,但用于具有不同技术名称的其他相关事物。 (例如执行无符号加法)
标签: c assembly gcc x86-64 integer-overflow