Вероятно, это не лучший заголовок для вопроса, но я хочу просто передать несколько строк сборки в макрос nasm. Или, что то же самое, я хочу, чтобы макрос реализовал шаблонные «верх» и «низ» некоторого блока кода, но с произвольной серединой.
В качестве конкретного примера рассмотрим следующий источник nasm:
%assign regn 8
%rep 8
%define reg r %+ regn
lea reg, [rsp - 8] ; body
push reg ; body
%assign regn (regn + 1)
%endrep
Это перебирает все регистры от r8 до r15 и генерирует две строки «основного» кода для каждой, с результатом вроде:
lea r8,[rsp-0x8]
push r8
lea r9,[rsp-0x8]
push r9
lea r10,[rsp-0x8]
push r10
lea r11,[rsp-0x8]
push r11
lea r12,[rsp-0x8]
push r12
lea r13,[rsp-0x8]
push r13
lea r14,[rsp-0x8]
push r14
lea r15,[rsp-0x8]
push r15
Я хотел бы извлечь этот шаблон "цикл по 8 регистрам", который представляет собой все строки, не отмеченные выше как ; body, в какой-то макрос, чтобы я мог вызывать его с разными типами тел.
Если бы тело было только одной строкой, это было бы так же просто, как:
%macro loop_r8_r15 1
%assign regn 8
%rep 8
%define reg r %+ regn
%1 ; body
%assign regn (regn + 1)
%endrep
Однако я не могу найти естественный способ расширить это на несколько строк. Думаю, я мог бы использовать макрос, который принимает один или несколько аргументов, а затем «перебирает» их в теле, но это означает, что вам нужно записать вызов макроса в одной строке со вставкой каждой строки, а не естественным однострочным -за инструкцию, как вы хотели бы это написать. Я также не уверен, как это работает, если само тело содержит вызовы макросов или другие директивы.
@PeterCordes, на самом деле это являетсянастоящий код для проверки задержек при поиске указателей. Я уверен, что это могло бы быть более эффективным: например, вы могли бы легко векторизовать всю часть push с помощью широковещательной передачи, и пара добавлений, а затем записать все это двумя 32-байтовыми записями - но это код настройки за пределами критической области, поэтому «правила простоты».





Я не знаю, возможно ли это с макроязыком NASM. Я предполагаю, что пример, который вы приготовили, не был настоящим кодом, но если бы это было так, вы могли бы сделать это более эффективно на Intel (без операций синхронизации стека) с
lea r9, [r8 - 0x8]/lea r10, [r8 - 0x10]и так далее.