Как вы перемещаете ярлык в регистр в сборке intel x86_64 intel? [Дубликат]

lambda выражение с пустым списком захвата может быть неявно преобразовано в указатель функции. Но указатель функции predicate принимает T как свой параметр, который нужно вывести. Преобразование типа не рассматривается в выводе типа шаблона, T не может быть выведено; как указано в сообщении об ошибке, шаблон-кандидат (т.е. binsearch) игнорируется.

Вы можете использовать operator+ для достижения этого, он преобразует лямбда в указатель функции, который будет передан в binsearch позже, а затем T будет успешно выведен [1].

binsearch(a, +[](int e) -> bool { return e >= 5; });
//           ~

Конечно, вы можете явно использовать static_cast:

binsearch(a, static_cast([](int e) -> bool { return e >= 5; }));

Обратите внимание, что если вы меняете predicate, который не зависит от T, т. е. bool (*predicate)(int), прохождение лямбда с пустым списком захвата тоже будет работать; лямбда-выражение будет неявно преобразовываться в указатель функции.


Другое решение изменяет тип параметра с указателя функции на std::function, что является более общим для функторов:

template  int binsearch(const std::vector &ts, std::function::value_type)> predicate) {
    ...
}

, затем

binsearch(a, [](int e) -> bool { return e >= 5; });

[1] Положительная лямбда: '+ [] {}' - Какое колдовство это?

0
задан Peter Cordes 7 September 2016 в 03:10
поделиться

1 ответ

В режиме GAS .intel_syntax noprefix:

  • OFFSET symbol работает как AT & amp; T $symbol. Это похоже на MASM.
  • symbol работает как AT & amp; T symbol (т. Е. Разыменование).
  • [symbol] всегда является эффективным адресом, , в ГАЗ и NASM / YASM. LEA не загружается с адреса, но он все еще использует кодировку машинного интерфейса памяти. (Вот почему он использует тот же синтаксис).

Совет. Если вы знаете синтаксис AT & amp; T или синтаксис NASM, для чего-то используйте его для создания кодировки хотите, а затем разобрать с помощью objdump -Mintel, чтобы узнать правильный синтаксис для .intel_syntax noprefx.

BTW, никакие проекты с открытым кодом, о которых я знаю, содержат исходный код GAS intel_syntax. Если они используют газ, они используют синтаксис AT & amp; T. В противном случае они используют NASM / YASM. (Иногда вы также видите MSVC inline asm в проектах с открытым исходным кодом).


GNU, поскольку режим .intel_syntax noprefix несколько похож на MASM, за исключением того, что магия не зависит от того, как определяются символы.

mov rdx, symbol всегда всегда нагрузка. Значением символа является его адрес. то есть использование .set создает (или изменяет) символ, который ведет себя точно так же, как помещает метку на что-то.

mov rdx, OFFSET symbol будет собраться к mov r/m64, imm32. Я забываю, если режим синтаксиса Intel позволяет собирать movabs r64, imm64 с большими операндами, но это не имеет значения, потому что статические данные / кодовые адреса всегда находятся в низком виртуальном адресном пространстве 2GiB, поэтому они вписываются в 32-битные расширенные подписки. (Это безопасно для записи mov edx, OFFSET symbol).

3
ответ дан Peter Cordes 18 August 2018 в 09:22
поделиться
  • 1
    Спасибо за подробный ответ, Питер! – Alex Reinking 7 September 2016 в 19:14
  • 2
    "нет проектов с открытым кодом, о которых я знаю, содержат исходный код GAS intel_syntax. & quot; Вау, действительно? Возможно, это все, к чему вы привыкли, но я ненавижу синтаксис AT & amp; T. Если бы я собирался потратить какое-то усилие на запись / поддержку встроенной сборки GAS, я бы определенно предпочитал использовать синтаксис Intel. Есть ли какая-то техническая причина, почему люди этого не делают? Например, существуют ли существенные ограничения GAS в отношении синтаксиса Intel? (Я в основном парень MSVC. Синтаксис MASM велик, но невозможность указать входные параметры для встроенной сборки затрудняет использование для оптимизации .) – Cody Gray♦ 8 September 2016 в 09:43
  • 3
    @CodyGray: Когда я впервые учил себя x86 asm, я был использован для синтаксиса AT & amp; T, потому что это то, что использовали gcc / objdump. Явный $ для непосредственных операндов был большим плюсом. Но как только я понял, что единственная настоящая инсталляция в синтаксисе Intel и немного привыкла к этому, я начал понимать, что читать проще. Назначьте слева и более симпатичный синтаксис операнда памяти. Я всегда использую режим Intel-синтаксиса на Godbolt и тому подобное. Я использую только синтаксис AT & amp; T при записи отчетов об ошибках с ошибкой gcc, так как это похоже на то, что выбирают компиляторы. – Peter Cordes 8 September 2016 в 10:02
  • 4
    @ Коди: насколько технические ограничения, я так не думаю. Но это не так хорошо документировано. Кажется, я вспоминаю вопрос SO, в котором было некоторое ощущение, что GAS intel_syntax является полу-двусмысленным или ограниченным, но я не могу вспомнить, в чем проблема. Я думаю, что вам нужен синтаксис Intel, хотя обычно лучше использовать NASM или YASM, поэтому необычно идти на полпути и использовать газ .intel_syntax. – Peter Cordes 8 September 2016 в 10:07
  • 5
    @CodyGray: О, я просто вспомнил один конкретный недостаток: у газа .intel_syntax все еще есть синтаксис AT & amp; T design , что некоторые формы некоммутативных x87 insns (например, fdivr и fdiv ) обращаются вспять. Я просто проверил это, и NASM fsubr st3, st0 является objdump (AT & amp; T) fsub %st,%st(3), а также objdump -Mintel fsub st(3),st. (обратите внимание на мнемонику fsub в обоих случаях.) Objconv-fyasm Агнера Фога разбирает ее как fsubr st3, st(0) с правильной мнемонической. Thumbs down для ошибок дизайна, которые не могут быть исправлены по соображениям совместимости – Peter Cordes 8 September 2016 в 10:27
Другие вопросы по тегам:

Похожие вопросы: