我有几个关于x86或x86_64架构上的除法溢出错误的问题.最近我一直在阅读整数溢出.通常,当算术运算导致整数溢出时,FLAGS寄存器中的进位或溢出位置位.但显然,根据这篇文章,除法运算产生的溢出不会设置溢出位,而是触发硬件异常,类似于除以零时.
现在,由除法产生的整数溢出比乘法更加罕见.只有几种方法可以触发除法溢出.一种方法是做一些事情:
int16_t a = -32768;
int16_t b = -1;
int16_t c = a / b;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,由于有符号整数的二进制补码表示,您不能在带符号的16位整数中表示正32768,因此除法运算溢出,导致错误值-32768.
几个问题:
1)与本文所说的相反,上述内容并未导致硬件异常.我正在使用运行Linux的x86_64机器,当我除以零时程序终止于Floating point exception.但是当我导致除法溢出时,程序会像往常一样继续,默默地忽略错误的商.那么为什么这不会导致硬件异常呢?
2)为什么硬件会严重处理除法错误,而不是其他算术溢出?为什么要乘法溢出(这是很多更可能发生意外)的硬件被忽略,但一个分区溢出应该引发重大的中断?
=========== 编辑 ==============
好的,谢谢大家的回复.我得到的回答基本上说上面的16位整数除法不应该导致硬件故障,因为商仍然小于寄存器大小.我不明白这一点.在这种情况下,存储商的寄存器是16位 - 这太小而不能存储有符号的正32768.那么为什么不引发硬件异常呢?
好的,让我们直接在GCC内联汇编中执行此操作,看看会发生什么:
int16_t a = -32768;
int16_t b = -1;
__asm__
(
"xorw %%dx, %%dx;" // Clear the DX register (upper-bits of dividend)
"movw %1, %%ax;" // Load lower bits of dividend into AX
"movw %2, %%bx;" // Load the divisor into BX
"idivw %%bx;" …Run Code Online (Sandbox Code Playgroud) 是否有g ++警告或其他工具可以识别整数除法(截断为零)?我有成千上万行代码进行计算,不可避免地会出现数值错误,这通常是由于需要定位的"float = int/int".我需要一种合理的方法来找到它们.
在VB.NET中,即使两个操作数都是整数,'/'运算符也会导致值浮动(如果结果是非整数).
所以我尝试使用'\'运算符产生整数值而不管操作数.
所以我认为'\'是整数除法
2.5\3结果0
现在我尝试了
1.5\2
我预计它会为0但它会导致1.
现在,这是一个错误还是正确的结果?
实际上是什么'''运算符?
如果它是一个错误,它通过VB6存在
英特尔在x86处理器中实现了哪种整数除法算法?
在我学习NASM的过程中,我试图创建一个非常简单的程序来进行除法并输出结果.
通过书籍,一切都应该运行良好.我将15除以3,它应该自动存储在AX寄存器中,然后我转移到ecx进行输出.
但是,当我尝试编译时,我收到错误
nums.asm:6: error: invalid combination of opcode and operands
nums.asm:7: error: invalid combination of opcode and operands
Run Code Online (Sandbox Code Playgroud)
有谁知道第6和第7行有什么问题吗?
这是我的代码:
segment .text
global main
main:
div 3, 15
mov ecx, ax
mov ebx,1 ; arg1, where to write, screen
mov eax,4 ; write sysout command to int 80 hex
int 0x80 ; interrupt 80 hex, call kernel
exit: mov eax, 1
xor ebx, ebx
int 0x80
Run Code Online (Sandbox Code Playgroud) 如" 在C++中使用负数进行整数除法 "中所述,在C99之前的C中(即在C89中)和在C++之前的C++中(即在C++ 98和C++ 03中),用于整数除法计算,其中两个操作数都是负数,余数的符号(或等效地,商的舍入方向)是实现定义的.
然后是标准函数std::div,它被指定为将商截断为零(即,余数与被除数(分子)具有相同的符号)(例如,参见"div()库函数的目的是什么?"的答案.
这是glibc的div()(源代码)代码(也引用" Is div function useful(stdlib.h)? "):
(注:div_t定义为:
typedef struct
{
int quot;
int rem;
} div_t;
Run Code Online (Sandbox Code Playgroud)
- 结束说明.)
/* Return the `div_t' representation of NUMER over DENOM. */
div_t
div (numer, denom)
int numer, denom;
{
div_t result;
result.quot = numer / denom;
result.rem = numer % denom;
/* The ANSI standard says that |QUOT| <= |NUMER / DENOM|, where …Run Code Online (Sandbox Code Playgroud) 下面是我在C中编写的主要功能(对于PIC18F8722微处理器),试图以unsigned int函数设置的特定频率驱动2个多路复用7段显示get_ADC_value().显示屏还显示当前的多路复用频率.该频率范围设置#define在LAB_Fmin和LAB_Fmax范围内,并且必须get_ADC_value()随着从0增加或减少到255 而缩放.
但是这段代码不起作用,因为我认为有隐式转换int为floatat freq =.
挑战是使用浮点数修复此错误,并仅使用整数类型(int,char...)查找替代方法.
while (1) {
unsigned int x, y, z;
float freq, delay;
x = get_ADC_value();
y = x & 0b00001111;
z = (x & 0b11110000) >> 4 ;
freq = LAB_Fmin + (((LAB_Fmax) - (LAB_Fmin))/ 255)*x ;
delay = 1/(freq*1000); // convert hZ to ms delay accurately
LATF = int_to_SSD(y);
LATH = 0b11111110; //enable 7seg U1
for (unsigned int …Run Code Online (Sandbox Code Playgroud) 对https://ridiculousfish.com/blog/posts/benchmarking-libdivide-m1-avx512.html的分析发现,新的 Apple CPU 花费了大量资源使整数除法速度大大加快。
这是一件令人惊讶的事情。根据我的经验,整数除法并没有真正使用,除非在除以编译时间常数的情况下,可以用移位或乘法代替。
更令人惊讶的是在https://news.ycombinator.com/item?id=27133804的讨论中有人说
当我一直在对性能关键代码进行微优化时,整数除法经常作为一个热点出现。
现在我真的很好奇:人们在做什么,使整数除法成为瓶颈?我正在考虑可以在哪里使用它。我见过的案例:
浮点模拟。但是现在,唯一没有硬件浮点的 CPU 是微型微控制器,无论如何也不会有硬件整数除法。
带有桶数的哈希表是素数,以获得一点额外的随机性。但是人们早就知道这不是最好的做事方式。如果您不相信您的散列函数提供足够的随机性,请获得更好的散列函数。
使用固定点坐标的早期 3D,如 PlayStation 1。但是现在每个人都在做浮点 3D。
那么所有这些整数除法究竟是用来做什么的呢?
performance cpu-architecture division integer-division instructions
如何有效计算 2\xc2\xb9\xc2\xb2\xe2\x81\xb8 % n,其中 n 为uint64_t(且非零)?
如果我能够像_udiv128MSVC 的内在那样缩小范围,我可以这样做:
uint64_t remainder;\n_udiv128(1, 0, n, &remainder);\n_udiv128(remainder, 0, n, &remainder);\nRun Code Online (Sandbox Code Playgroud)\n但这是两条慢指令,更不用说像 ARM 这样的 CPU 没有缩小除法。有没有更好的办法?
\n\n我正在用java编程,我需要制定一个算法.算法的要求是:
n,m,k,n几k部分,以便k-parts 的总和等于n,每个部分是1和之间的整数m.例如,输入集:
n = 7; m = 3; k = 4
Run Code Online (Sandbox Code Playgroud)
我们可以制定两种不同的组合:
7 = 2 + 2 + 2 + 1
Run Code Online (Sandbox Code Playgroud)
和
7 = 3 + 2 + 1 + 1
Run Code Online (Sandbox Code Playgroud)
谢谢你们.
integer-division ×10
c ×4
assembly ×3
c++ ×3
x86 ×3
division ×2
algorithm ×1
glibc ×1
hardware ×1
instructions ×1
intel ×1
java ×1
microchip ×1
nasm ×1
optimization ×1
performance ×1
truncation ×1
vb.net ×1