Как использовать переменное смещение во встроенной сборке? - PullRequest
0 голосов
/ 01 июля 2019

Общая проблема, которую я пытаюсь решить, - это вызвать printf, извлекая строку формата и аргументы из необработанного буфера.Пока что решение, которое, кажется, работает лучше всего, заключается в использовании встроенной сборки в качестве способа передачи аргументов с переменным смешанным типом в функцию.

В настоящее время у нас есть символы и целые числа, работающие безупречно, и плавающие / удваиваются, работая, пока мы не должны передать их в стек.(Прохождение через xmm0 - xmm7 работает для нас безупречно).Цель здесь - поместить эти значения с плавающей запятой в стек после того, как все xmm0-xmm7 будут использованы.Эти значения будут затем использованы в последующем вызове printf.То, как мы справляемся с этим для символов и целых чисел, заключается в том, чтобы поместить их в стек просто с помощью инструкции push, которую вызов printf может использовать очень хорошо, но так как эта инструкция не работает для плавающей запятойзначения, которые мы должны вручную «вставить» в стек, используя метод, приведенный ниже.Я понимаю, что это очень неправильный способ справиться с этим, но мы не смогли найти выход из этого.

В настоящее время наше решение для передачи более восьми значений с плавающей запятой в стек требует, чтобы мы знали смещение аргумента, передаваемого нашему вызову printf.В этом случае смещения соответствуют 8-байтовым приращениям.9-й аргумент должен быть загружен в (%rsp), 10-й в 0x8(%rsp), 11-й в 0x10(%rsp) 12-й в 0x18(%rsp), а остальные аргументы продолжают эту тенденцию.

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

Ниже приведен небольшой фрагмент того, что мы делаем в настоящее время, чтобы переместить один из аргументов в соответствующее место для вызова printf для доступа к аргументу.

double myDouble = 1.23;
asm volatile (
  "movsd %0, 0x8(%%rsp)" #The 0x8 is the offset we are hoping to pass in
:: "m" (myDouble)
);

Я ищуспособ сохранить это смещение (0x8, 0x10, 0x18, ...) в переменной, которая может быть увеличена на восемь при обработке аргументов, хотя теперь я боюсь, что это сломается, как только мы начнем смешивать в более смешанные типизированные значения, которыевыталкиваются в стек.

Любое руководство будет с благодарностью!

1 Ответ

1 голос
/ 01 июля 2019

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

int foo(int64_t offset, double value)
{
    asm volatile (
        "movsd %0, (%%rsp,%1)" :: "x" (value), "r" (offset)
        : "memory"
    );
}

Вы также можете позволить процессору выполнять умножение на 8, используя режим адресации с масштабированным смещением:

int foo(int64_t offset, double value)
{
    asm volatile (
        "movsd %0, (%%rsp,%1,8)" :: "x" (value), "r" (offset)
        : "memory"
    );
}

Или, если вы хотите эмулировать push, то sub $8, %%rsp / movsd %0, (%%rsp), но вы не можете связываться с указателем стека из встроенного asm, не нарушая сгенерированный компилятором код.

...