cpp-ru / ideas

Идеи по улучшению языка C++ для обсуждения
https://cpp-ru.github.io/proposals
Creative Commons Zero v1.0 Universal
89 stars 0 forks source link

Ассемблерные функции. #259

Open apolukhin opened 3 years ago

apolukhin commented 3 years ago

Перенос предложения: голоса +6, -4 Автор идеи: int33h-tm

Добавить в язык возможность написания чисто ассемблерных функций.

Во многих современных компиляторах С++ есть очень нетривиальные, но все же возможности написания ассемблерных вставок. Но их поддержка на уровне компилятора, в некоторых случаях, оставляет желать лучшего...Но давайте не будем заострять внимание именно на ассемблерных вставках, а подумаем немножечко глобальнее... С++ наследник языка С, который являет собой язык процедурного программирования, следовательно объектом нашего рассмотрения должна стать функция(процедура)...

Идея довольно проста. Нам нужно придумать вариант реализации функции с внутренним ассемблерным кодом, которая сможет встроиться в наш код с помощью компилятора.(В современном gcc, есть возможность вызова некоторых команд процессора напрямую с помощью специальных intrinsic-функций, которые говорят компилятору выполнить прямую подстановку, но эти средства крайне ограниченны) Недолгими размышлениями мы приходим к такому первоначальному ответу:

asm <retval> func([params]){
    //только aссемблерный код
}

(Ассемблерный код напрямую подставляется компилятором на место функции без всяких проверок. В случае вызова какой-либо функии, компилятор должен заменить ее вызов исходя из своей внутренней логики) Но тут надо вспомнить, что языки С/С++ являются кроссплатформенными, чем ассемблер не может похвастаться. Это надо чем-то компенсировать... И тут вспоминается, что в последних стандартах(C++14) в язык была добавлена возможность помечать некоторые функции словом [[deprecated]]. Раз мы можем теперь помечать функции, то почему бы не пометить нашу функцию, как функцию для определенной платформы...

[[platform(x86)]]
asm <retval> func([params]){
    //ассемблерный код для платформы x86
}

Таких функций мы можем реализовать огромное множество для самых разных платформ(главное, чтобы совпадала сигнатура). Также желательно добавить еще способ дополнительного описания флагов процессора, таких как SSE, AVX и других, для того, чтобы использовать более расширенный набор команд.

Теперь встает вопрос, а как компилятору определить какую из них выбрать? Тут тоже можно дать ответ: Подбирается наиболее подходящая функция в следующем порядке:

1)нужная платформа + флаги Если есть несколько доступных(все указанные флаги у этого процессора есть) реализаций под конкретную платформу, но с разным кол-вом флагов, то будет выбираться вариант с наибольшим кол-вом.

2)общая реализация.(обычный С/С++ код) Если нет общей реализации, то сообщить об ошибке компиляции под требуемую платформу.

Готово! Хотел бы я сказать, но ведь нужно еще подумать о передаче параметров...

В ассемблере параметры могут передаваться как через стек, так и через регисты => нужно научиться передавать параметры через регистры => Т.к. мы уже указали платформу до описания сигнатруры, то можем использовать следующую кострукцию:

//функция inc (префиксный оператор ++)
[[platform(x86), core_flags(...)]]
asm int inc(register int ebx) //register <type> <reg_name>
{
    inc ebx
    mov eax, ebx //по умолчанию возвращаемое значение кладется в регистр rax/eax/ax.
    ret
}

...

int main()
{
    int x = 0;
    ...
    inc(x);
//equal to:
//  mov ebx, &x
//  call inc
    ...
}

Вот теперь, наверно, все.

apolukhin commented 3 years ago

yndx-antoshkka, 10 января 2018, 12:40 Идея интересная но в таком виде работать не будет:

Начните продумывать идею с https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html Там описаны дополнительные подсказки при ассемблерной вставке, необходимые компилятору для генерации эффективного кода вокруг ассемблерной вставки.

smertigdon, 12 января 2018, 15:20 С текущей реализацией все ключевые слова ассемблера автоматически становятся ключевыми словами C++. Это сильно раздувает стандарт и грамматику, добавляет неоднозначности. Тянуть один язык в другой - не шибко хорошая идея, хоть я и сам пользуюсь асм-вставками.

Fihtangolz, 18 июля 2018, 0:30 smertigdon, в чем проблема сделать inbrace лексику, просто берем написанно и с небольшими изменениями выплевываем ассеблеру тоже самое по сути что мс, каша в виде "" в гцц откровенно говоря выглядит не слишком дружелюбно для чтения. Давно пора стандартиировать ситаксис вставок, конечно эту проблему можно решить внешней библиотекой с парой макросов, но ассемблерная вставка самом по себе громозкая нехватаеет туда еще пары макросов для консистентности

Виктор Губин, 28 марта 2018, 14:42 Почему-бы не стандартизировать сам синтаксис ассемблерных вставок?

В GCC имеем:

__asm__ ( "addq %rbx,%rax\n" : "=a"(ret), "a"(lsh), "b"(rhs) : );

В MS VC++

__asm  
{
  mov rax,lsh
  mov rbx,rhs
  add rax,rbx
  mov ret,rax
}

Ассемблерный код понятное дело зависит от целевого процессора, но синтаксис самой вставки разный от компилятора к компилятору.

В итоге идетичный код нужно дублировать как - для типа CPU или OS, так и для разных компиляторов.

vlad-ger-m, 28 апреля 2018, 15:11 Хорошая идея -

("вариант реализации функции с внутренним ассемблерным кодом, которая сможет встроиться в наш код с помощью компилятора. В современном gcc, есть возможность вызова некоторых команд процессора напрямую с помощью специальных intrinsic-функций". )