Индекс входного параметра при использовании модификатора «+» в расширенном выходном параметре asm? - PullRequest
0 голосов
/ 08 октября 2019

Расширенный asm дает следующее описание относительно модификатора "+":

Операнды, использующие модификатор ограничения «+», считаются в качестве двух операндов (то есть оба в качестве входных данныхи вывод) к максимальному значению 30 операндов на оператор asm.

Поэтому я предполагаю, что нет необходимости упоминать выходной операнд с модификатором "+" в разделе ввода снова, но этоне указано, как определить их индекс. Я написал следующий пример Godbolt :

#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>

void asm_add(uint64_t o1, uint64_t o2, uint64_t o3){
    __asm__ volatile (
        "addq %2, %3\n\
        addq %2, %4":    
        "+r" (o2), "+r" (o3):
        "r" (o1):
        "cc"
    );
    printf("o2 = %" PRIu64 "\n", o2);
    printf("o3 = %" PRIu64 "\n", o3);
}


int main(void){
    asm_add(20, 30, 40);
}

На котором напечатано

o2 = 50
o3 = 60

Является ли шаблон с использованием +

__asm__ volatile (
   "addq %2, %3\n\
    addq %2, %4":    
    "+r" (o2), "+r" (o3):
    "r" (o1):
    "cc"
);

точнотак же, как

__asm__ volatile (
    "addq %2, %3\n\
    addq %2, %4":    
    "+r" (o2), "+r" (o3):
    "r" (o1), "0" (o2), "1" (o3):
    "cc"
);

, где все входы указаны явно? Таким образом, в первом примере «неявные» входы добавляются.

1 Ответ

2 голосов
/ 09 октября 2019

Используя "+r" (o2), вы говорите, что этот параметр должен содержать o2 при входе в блок asm и содержать обновленное значение при выходе.

Другими словами,% 0 описывает оба вводаи вывод. Тот факт, что вы можете (по-видимому?) Ссылочные индексы больше, чем число параметров, является недокументированной причудой. Не зависите от этого.

Вы могли бы также рассмотреть возможность использования символических имен, которые (я считаю) легче читать, особенно с увеличением количества строк asm. Имена особенно полезны, когда вы впервые создаете asm, и есть потенциал для добавления / удаления параметров. Необходимость перенумерации всего болезненна и подвержена ошибкам:

__asm__ volatile (
    "addq %[o1], %[o2]\n\
    addq %[o1], %[o3]":    
    [o2] "+r" (o2), [o3] "+r" (o3):
    [o1] "r" (o1):
    "cc"
);

Наконец, рассмотрим , не использующий встроенный ассм для чего-либо, кроме образовательных целей. И даже в этом случае inline asm - самый сложный способ выучить asm.

...