_BitScanForward64返回错误的答案在c ++。exe(rubenvb-4.7.2-release) [英] _BitScanForward64 returns wrong answer in c++.exe (rubenvb-4.7.2-release)

查看:1572
本文介绍了_BitScanForward64返回错误的答案在c ++。exe(rubenvb-4.7.2-release)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

长时间的MSVC用户,新到gcc(所以忍受我)。



我使用的是rubenvb版本的c ++(参见版本的主题, m大楼为64位)在Windows 7和我有一个问题,使用_BitScanForward64。一些示例代码如下所示:

  int __cdecl main(int argc,char * argv [])
{
DWORD d =(DWORD)atoi(argv [1]);

DWORD ix,ix2;
ix2 = _BitScanForward64(& ix,d);
printf(bsf%u%u\\\
,ix,ix2);
}

我正在编译:



C:\Program Files \gcc2\mingw64\bin\c ++。exe-o iTot.exe -mno-ms-bitfields -march = native -momit-leaf-frame-pointer - mwin32 -Os -fomit-frame-pointer -m64 -msse4 -mpopcnt -D WINDOWS main.cpp



当我使用参数8运行iTot.exe时, _BitScanForward64会将ix设置为3.这就是MSVC的作用。但是,ix是0,ix2是1。



另外,看看汇编器,我看到:

  bsfq QWORD PTR 44 [rsp],rax#MEM [(volatile LONG64 *)& ix],Mask 

在这种情况下,为什么gcc强制写一个内存写+读这里?



>


  1. 是_BitScanForward64不知何故应该在gcc下调用不同?

  2. 为什么_BitScanForward64内存强制执行内存写操作?
  3. li>
  4. 盯着-S的汇编器输出,我看不到生成的代码有什么问题。但是,使用 objdump.exe -d -Mintel ,我看到,而不是使用上面的asm代码(似乎它会工作),它实际上产生了相反:



    bsf rax,QWORD PTR [rsp + 0x2c]




WTF?为什么-S对我说谎?



像我说的,我是新来的gcc,所以如果我只是做一些蠢事,对我温柔。谢谢。

解决方案

好的,我想我已经回答了我自己的问题。感谢Joachim PileBorg让我看看定义在哪里,和Alexey Frunze谁指出params 不能落后。





当前的定义:

  __ CRT_INLINE BOOLEAN _BitScanForward64(DWORD * Index,DWORD64 Mask){
__asm__ __volatile __(bsfq%1,%0: = r(Mask),= m(*(volatile LONG64 *)Index)));
return Mask!= 0;
}



我的定义:

  __ CRT_INLINE BOOLEAN BSF(DWORD * Index,DWORD64 Mask){
LONG64 t;
__asm__(bsfq%0,%1:= r(Mask),= r(t));
* Index = t;
return Mask!= 0;
}

注意移除了(不需要的)volatile, bsfq,从= m到= r的变化,等等。基本上,这个定义看起来是错误的,并且仍然可以编译。



我猜写了这个人的人看了BitScanForward64的原型,知道其中的一个参数必须是内存,并且因为可以是BSF的内存的唯一一个是p2,这是他们做的。写入时,代码将读取p2的未写入内容,并扫描它的位。它编译,但产生错误的答案。



所以,为了接受我的问题:


  1. 不,我没有正确地调用它。 winnt.h中的定义是错误的。实际上,在该文件中可能有一个有类似问题的(_BitScanForward,_BitScanForward64,_BitScanReverse,_BitScanReverse64等)。

  2. 它强制写入内存,因为winnt.h中的代码错了。我提出的更改不会强制任何内存访问。

  3. -S写入输出文件不正确(objdump正确)。使用我上面的定义生成:

     调用atoi 
    lea rcx,.LC0 [rip]
    / APP
    #7m.cpp1
    bsfq rax,rdx
    / NO_APP
    call printf


这不是可执行文件中实际的内容。实际的可执行文件包含(正确的)定义:

  bsfq rdx,rax 

虽然我不喜欢修改系统头文件,它似乎是我的答案在这里。如果任何人知道如何/在哪里报告这个问题,所以它得到固定(正如我提到,我使用reubenvb),我可以报告这两个问题所以(希望)这是固定的每个人。


Long time MSVC user, new to gcc (so bear with me).

I am using the rubenvb version of c++ (see version in subject, yes I'm building for 64bit) on Windows 7 and I'm having a problem using _BitScanForward64. Some sample code looks like this:

int __cdecl main(int argc, char* argv[])
{
    DWORD d = (DWORD)atoi(argv[1]);

    DWORD ix, ix2;
    ix2 = _BitScanForward64(&ix, d);
    printf("bsf %u %u\n", ix, ix2);
}

I am compiling with:

"C:\Program Files\gcc2\mingw64\bin\c++.exe" -o iTot.exe -mno-ms-bitfields -march=native -momit-leaf-frame-pointer -mwin32 -Os -fomit-frame-pointer -m64 -msse4 -mpopcnt -D WINDOWS main.cpp

When I run iTot.exe using the parameter 8, I expected that _BitScanForward64 would set ix to 3. That's what MSVC does. However, ix is 0 and ix2 is 1.

Also, looking at the assembler, I see:

bsfq QWORD PTR 44[rsp],rax   # MEM[(volatile LONG64 *)&ix], Mask

Under the circumstances, why does gcc force a memory write+read here?

So, a few questions:

  1. Is _BitScanForward64 somehow supposed to be called differently under gcc? If I'm just calling it wrong, that would be good to know (although the incompatibility with MSVC would be a pain).
  2. Why does the _BitScanForward64 intrinsic force a memory write?
  3. Staring at the assembler output from -S, I couldn't see anything wrong with the code being generated. However, using objdump.exe -d -Mintel, I see that rather than using the asm code above (which seems like it would work), it actually produced the reverse:

    bsf rax,QWORD PTR [rsp+0x2c]

WTF? Why is -S lying to me?

Like I said, I'm new to gcc, so if I'm just doing something dumb, be gentle with me. Thanks.

解决方案

Ok, I think I've answered my own questions. Thanks to Joachim PileBorg who made me look at where the definition was, and Alexey Frunze who pointed out that the params can't be backward.

While I'm too new to gcc to say this authoritatively, I believe the definition for _BitScanForward64 in winnt.h is very wrong.

The current definition:

__CRT_INLINE BOOLEAN _BitScanForward64(DWORD *Index,DWORD64 Mask) {
  __asm__ __volatile__("bsfq %1,%0" : "=r" (Mask),"=m" ((*(volatile LONG64 *)Index)));
  return Mask!=0;
}

My definition:

__CRT_INLINE BOOLEAN BSF(DWORD *Index,DWORD64 Mask) {
  LONG64 t;
  __asm__ ("bsfq %0,%1" : "=r" (Mask),"=r" (t));
  *Index = t;
  return Mask!=0;
}

Note the removal of the (unneeded) volatile, the reversal of the parameters to bsfq, the change from =m to =r, etc. Basically, it appears this definition is as wrong as it could be and still compile.

I'm guessing the person who wrote this looked at the prototype for BitScanForward64 and "knew" that one of the parameters had to be memory, and since the only one that can be memory for BSF is p2, that's what they did. As written, the code will read the unwritten contents of p2 and scan it for bits. It compiles, but produces the wrong answer.

So, to take my questions in order:

  1. No, I wasn't calling it incorrectly. The definition in winnt.h is just wrong. In fact, there's probably a bunch in that file that have a similar problem (_BitScanForward, _BitScanForward64, _BitScanReverse, _BitScanReverse64, etc).
  2. It forces a memory write because the code in winnt.h was wrong. My proposed change does not force any memory accesses.
  3. -S is writing the output file incorrectly (objdump has it right). Using my definition above produces:

    call    atoi
    lea rcx, .LC0[rip]
    /APP
    # 7 "m.cpp" 1
    bsfq rax,rdx
    /NO_APP
    call    printf
    

And this isn't what is actually in the executable file. The actual executable file contains the (correct) definition:

bsfq rdx,rax

While I'm not excited about modifying system header files, it appears that's going to be my answer here. If anyone knows how/where to report this problem so it gets fixed (as I mentioned, I'm using reubenvb), I could report these 2 issues so (hopefully) this gets fixed for everyone.

这篇关于_BitScanForward64返回错误的答案在c ++。exe(rubenvb-4.7.2-release)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆