asm error: «несоответствие типов операндов для« rol »» с несколькими входными операндами - PullRequest
0 голосов
/ 04 ноября 2018

Среда: Debian 9.5 - gcc 6.3.0

Я не могу заставить работать встроенную функцию сборки, когда пытаюсь использовать несколько InputOperands.

У меня работает следующий код (базовая rol функция, 1 InputOperand, предопределенный rol операнд):

#include <stdio.h>
#include <stdlib.h>

void asm_rol(int32_t* p_rolled)
{
    __asm__ volatile
    (
        ".intel_syntax noprefix;"
        "rol %0, 1;"
        :"=a"(*p_rolled)
        :"a"(*p_rolled)
        :"cc"
    );
}

int main(int argc, char** argv)
{
    int32_t test = 0x1;
    asm_rol(&test);

    printf("0x%08x\n", test);
    return 0;
}

Это печатает 0x00000002, и является правильным результатом rol 0x1, 1.

Теперь я не понимаю, почему следующий код не компилируется. Я думаю, что мое использование InputOperands плохо:

#include <stdio.h>
#include <stdlib.h>

void asm_rol(int32_t* p_rolled, int16_t i)
{
    __asm__ volatile
    (
        ".intel_syntax noprefix;"
        "rol %0, %1;"
        :"=a"(*p_rolled)
        :"a"(*p_rolled), "b"(i)
        :"cc"
    );
}

int main(int argc, char** argv)
{
    int32_t test = 0x1;
    asm_rol(&test, 1);

    printf("0x%08x\n", test);
    return 0;
}

gcc возвращает с ошибкой:

resolve.c: Assembler messages:
resolve.c:6: Error: operand type mismatch for `rol'

Я пробовал с int8_t и int32_t для i, это ничего не меняет.

Должен сказать, что я новичок во внедрении asm в C в этой среде, я только выполнил некоторые базовые встроенные сборки с Visual Studio для Windows.

1 Ответ

0 голосов
/ 04 ноября 2018

Как сказал Майкл Петч в комментариях,

единственный регистр, который разрешен для команды сдвига, которая контролирует количество бит для сдвига, это CL

Он также предоставил следующее решение:

void asm_rol(int32_t* p_rolled, int8_t i) {
    __asm__ volatile
    (
        ".intel_syntax noprefix;"
        "rol %0, %1;"
        :"+a"(*p_rolled)
        :"cI"(i) :"cc"
    );
}

C говорит использовать регистр CL (при условии, что вы меняете тип переменной i на int8_t вместо int16_t. Capital-Eye (I) говорит, что ограничение также может быть непосредственным значением от 0 до 32.

Как отмечали Майкл Петч и Питер Кордес в комментариях, мой код не работал, потому что я использовал %1 в качестве операнда rol, но правильная переменная была %2. Я сделал эту ошибку, потому что думал, что %#.

указывает только на InputOperands.

Майкл Петч и Питер Кордес также предоставили хорошую документацию:

(...) машинные ограничения можно найти здесь: gcc.gnu.org / onlinedocs / gcc /… под i386 info

Нет причин использовать встроенный asm для поворотов. Лучшие практики для операций кругового сдвига (поворота) в C ++

При отладке встроенного asm, вы должны посмотреть на asm, сгенерированный компилятором, чтобы увидеть, что он подставил в шаблон. например godbolt.org удобно: Как убрать "шум" из вывода сборки GCC / clang? . Вы даже можете делать такие вещи, как nop #% 0% 1% 2, чтобы просто посмотреть, что компилятор выбрал для всех операндов, независимо от того, ссылаетесь ли вы на них в шаблоне или нет. См. Также stackoverflow.com / tags / inline-assembly / info для получения дополнительных руководств и примеров.

...