windows — _BitScanForward64 возвращает неправильный ответ в c ++. exe (rubenvb-4.7.2-release)

Долгое время пользователь MSVC, новичок в gcc (так что терпите меня).

Я использую версию c ++ rubenvb (см. Версию в теме, да, я строю для 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\n", 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

Когда я запустил iTot.exe, используя параметр 8, я ожидал, что _BitScanForward64 установит для ix значение 3. Это то, что делает MSVC. Однако ix равен 0, а ix2 равен 1.

Также, глядя на ассемблера, я вижу:

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

При таких обстоятельствах, почему gcc заставляет память писать + читать здесь?

Итак, несколько вопросов:

  1. _BitScanForward64 как-то должен вызываться по-другому в gcc? Если бы я просто назвал это неправильно, это было бы полезно знать (хотя несовместимость с MSVC была бы болью).
  2. Почему встроенная функция _BitScanForward64 вызывает запись в память?
  3. Взглянув на вывод ассемблера из -S, я не увидел ничего плохого в генерируемом коде. Однако, используя objdump.exe -d -Mintel, Я вижу, что вместо того, чтобы использовать приведенный выше код asm (который, похоже, будет работать), он на самом деле произвел обратное:

    bsf rax, QWORD PTR [rsp + 0x2c]

WTF? Почему-лжет мне?

Как я уже сказал, я новичок в gcc, поэтому, если я просто делаю что-то глупое, будь осторожен со мной. Благодарю.

3

Решение

Хорошо, я думаю, что ответил на свои вопросы. Спасибо Joachim PileBorg, который заставил меня посмотреть, где было определение, и Алексею Фрунзе, который указал, что params не может быть отсталым

Хотя я слишком новичок в gcc, чтобы говорить об этом авторитетно, я считаю, что определение _BitScanForward64 в winnt.h очень неверно.

Текущее определение:

__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 все правильно). Использование моего определения выше дает:

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

И это не то, что на самом деле находится в исполняемом файле. Фактический исполняемый файл содержит (правильное) определение:

bsfq rdx,rax

Хотя я не в восторге от изменения файлов заголовков системы, похоже, что это будет мой ответ здесь. Если кто-то знает, как и где сообщить об этой проблеме, чтобы она была исправлена ​​(как я уже говорил, я использую reubenvb), я мог бы сообщить об этих двух проблемах, так что (надеюсь) это будет исправлено для всех.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]