Могу ли я создать метод C++ во внешней сборке (function.asm)?

Я пишу программу, которая требует одну функцию на ассемблере. Было бы очень полезно инкапсулировать функцию сборки в класс C++, чтобы ее собственные данные были изолированы, и я мог создать несколько экземпляров.

Если я создаю класс и вызываю внешнюю функцию из метода C++, функция является реентерабельной, даже если у нее есть собственный стек и локальные «переменные» в кадре стека.

Есть ли какой-нибудь способ сделать функцию сборки методом C++, возможно, используя изменение имени, чтобы функция была реализована в сборке, но прототип был объявлен внутри класса C++?

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

Вы, кажется, разбрасываете много слов, но не имеете смысла. Какой конкретный вариант использования не охватывает бесплатная функция?

Passer By 24.02.2019 06:33

Почему это требуется одна функция в сборке? Это кажется довольно маловероятным.

Ken White 24.02.2019 06:35

Вероятно, проще написать класс в C++ и добавить встроенную сборку в функцию-член, которая в этом нуждается.

Galik 24.02.2019 06:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
775
2

Ответы 2

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

Пример способа обертки:

extern "C" int asm_function(myclass *p, int a, double b);

class myclass {

    int q, r, member_array[4];
    int my_method(int a, double b) { return asm_function(this, a, b); }
};

Автономное определение my_method для x86-64 будет просто jmp asm_function, хвостовым вызовом, потому что аргументы идентичны. Итак, после встраивания у вас будет call asm_function вместо call _Zmyclass_mymethodZd или что-то в этом роде. (это я выдумал).


В GNU C/C++ также есть asm ключевое слово, чтобы установить имя символа asm для функции, вместо того, чтобы обычные правила изменения имен генерировали его из имени класса и функции-члена, а также типов аргументов. (Или с внешней буквой «C», обычно просто символом подчеркивания в начале или нет, в зависимости от платформы.)

class myclass {
    int q, r, member_array[4];
  public:
    int my_method(int a, double b) 
      asm("myclass_my_method_int_double");  // symbol name for separate asm
};

Затем в вашем файле .asm (например, синтаксис NASM для соглашения о вызовах x86-64 System V)

global myclass_my_method_int_double
myclass_my_method_int_double:
;; inputs: myclass *this  in  RDI,  int a  in ESI,  double b  in XMM0
   cvtsd2si eax, xmm0
   add      eax, [rdi+4]  ;; this->r
   imul     eax, esi
   ret

(Вы можете выбрать любое имя для своей ассемблерной функции; это не имеют для кодирования аргументов. Но это позволит вам перегрузить ее без конфликтующих имен символов.)

Пример на Годболте тестового вызывающего объекта, вызывающего способ asm(""):

void foo(myclass *p){
    p->my_method(1, 1.0);
}

компилируется в

foo(myclass*):
        movsd   xmm0, qword ptr [rip + .LCPI0_0] # xmm0 = mem[0],zero
        mov     esi, 1
        jmp     myclass_my_method_int_double    # TAILCALL

Обратите внимание, что звонящий издал jmp myclass_my_method_int_double, используя ваше имя, а не искаженное имя.

I am writing a program that requires one function in assembly.

Тогда по определению ваша программа становится намного меньше портативный. И зависит от соглашения о вызовах и АБИ вашей реализации C++ и вашей операционной системы.

Тогда было бы разумно использовать некоторые специфические функции компилятора (которых нет в переносимом стандарте С++ 11, например, в n3337).

Тогда я рекомендую воспользоваться преимуществами расширенной сборки ССАГПЗ. Прочтите главу о используя язык ассемблера с C (она также и, разумеется, применима к C++).

Непосредственно встраивая некоторые расширенные asm внутрь функции-члена C++, вы избегаете проблем с вызов какой-то функции. Вероятно, ваш ассемблерный код действительно короткий и выполняется быстро. Так что лучше встраивать его в функции C или C++, избегая затрат на пролог и эпилог вызова функции.

NB: В 2019 году нет экономического смысла тратить силы на написание большого кода на ассемблере: большинство оптимизирующих компиляторов выдают лучший ассемблерный код, чем может разумный программист (за разумное время). Таким образом, у вас есть стимул использовать фрагменты ассемблерного кода маленький в более крупных функциях C++ или C.

Другие вопросы по теме