Какая польза от сопоставления ограничений во встроенной сборке - PullRequest
1 голос
/ 09 января 2020

По следующей ссылке https://www.ibm.com/developerworks/library/l-ia/index.html

одна переменная может служить как входным, так и выходным операндом.

I написал следующий код:

#include <stdio.h>

int main()
{   
    int num = 1;
    asm volatile ("incl %0"
            :"=a"(num)
            :"0"(num));
    printf("num:%d\n", num);
    return 0;
}

Приведенный выше код увеличивает значение num.

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

asm volatile ("incl %0"
                :"=a"(num));

Ответы [ 2 ]

3 голосов
/ 09 января 2020

почему и когда мы должны использовать соответствующие ограничения

Это не тот вопрос, который вы задали; Вы спросили, зачем вообще нужен ввод, что должно быть достаточно очевидно, если вы знаете, что на самом деле означает синтаксис. (То, что "=r"(var) является чистым выводом, независимо от любого предыдущего значения, которое имела переменная C, как было бы var = 123;). Итак, "=r" с инструкцией inc похож на var = stale_garbage + 1;


Но в любом случае, как я уже говорил, интересным вопросом является ", почему существуют соответствующие ограничения, когда вы можете просто использовать "+r"(var) для операнда для чтения / записи вместо более сложного синтаксиса ограничения сопоставления?"

Они редко используются; обычно вы можете использовать одну и ту же переменную для ввода и вывода, особенно если у вас есть asm внутри C функции-оболочки . Но если вы не хотите использовать один и тот же C var для ввода и вывода, но по-прежнему нуждаетесь в том, чтобы они выбирали один и тот же регистр или память, тогда вам нужно соответствующее ограничение. Один вариант использования может заключать в себе системный вызов, это один вариант использования; Возможно, вы захотите использовать другую переменную C для номера вызова и возвращаемого значения. (За исключением того, что вы можете просто использовать "=a" и "a" вместо ограничения соответствия; у компилятора нет выбора.) Или, возможно, выходной var более узкого или другого типа, чем входной var, может быть другим вариантом использования. .

IIR C, x87 - другой вариант использования; Кажется, я помню, что "+t" не работает.

Я думаю, что ограничения "+r" RMW внутренне реализованы как выход со "скрытым" ограничением соответствия. Но в то время как %1 обычно выдает ошибку в шаблоне asm, который имеет только один операнд, если этот операнд является входным / выходным "+something", то G CC не отклоняет %1 как слишком большое число операндов. И если вы посмотрите на asm, чтобы увидеть, какой регистр или память он фактически выбрал для этого номера операнда за пределами допустимого диапазона, он совпадает с операндом ввода / вывода.

Так что "+r" в основном syntacti c сахар для соответствия ограничений. Я не уверен, было ли это новым в какой-то момент, и до G CC версии xy вам приходилось использовать соответствующие ограничения? Нередко можно увидеть примеры учебных пособий, в которых для обоих входных и выходных данных используются ограничения на сопоставление с одинаковыми переменными, которые проще читать с ограничениями "+" RMW.


Основы:

С ограничения как "a" и "=a" вам не нужно нужно соответствующее ограничение; в любом случае у компилятора есть только один выбор. Здесь полезно "=r", где компилятор может выбрать любой регистр, и вам нужно выбрать такой же регистр для входного операнда.

Если вы только что использовали "=r" и Отдельный "r" ввод, вы бы сказали компилятору, что он может использовать это как операцию копирования и чего угодно, оставляя исходный ввод неизмененным и создавая вывод в новом регистре. Или перезаписать ввод, если он хочет. Это было бы уместно для lea 1(%[srcreg]), %[dstreg], но не inc %0. Последний предполагает, что% 0 и% 1 - это один и тот же регистр, поэтому вам нужно что-то сделать, чтобы убедиться, что это правда!

3 голосов
/ 09 января 2020

Этот код:

asm volatile ("incl %0"
                :"=a"(num));

Не работает, потому что для увеличения значения в регистре (в данном случае на 1) необходимо прочитать исходное значение из регистра; 1 добавлено к нему; и значение записывается обратно в регистр. =a только говорит, что вывод регистра EAX будет перемещен в num после завершения, но компилятор не загрузит регистр EAX с исходным значением num. Приведенный выше код просто добавляет 1 к тому, что происходит в EAX (может быть что угодно), и помещает его в num, когда встроенная сборка завершена.

asm volatile ("incl %0"
        :"=a"(num)
        :"0"(num));

С другой стороны, это говорит о том, что num одновременно используется в качестве ввода (поэтому значение num перемещается в EAX) и что он также выводит значение в EAX, чтобы компилятор переместил значение в EAX в num, когда встроенная сборка будет завершена.

Можно было бы также переписать, чтобы использовать ограничение ввода / вывода (это делает то же самое):

asm volatile ("incl %0"
        :"+a"(num));

Здесь также нет необходимости в volatile, так как все побочные эффекты фиксируются в ограничениях. Добавление volatile излишне может привести к менее эффективной генерации кода, но код все равно будет работать. Я бы написал так:

asm ("incl %0"
     :"+a"(num));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...