2015-06-16 7 views
1

Я нашел этот макрос в исходном файле сборки, и я просто не могу понять, как он работает.Общие сведения о макросе NASM

Так первый я приезжаю вокруг этой функции (hevc_deblock.h):

cglobal hevc_v_loop_filter_chroma_8, 3, 5, 7, pix, stride, tc, pix0, r3stride 
    sub   pixq, 2 
    lea  r3strideq, [3*strideq] 
    mov   pix0q, pixq 
    add   pixq, r3strideq 
    TRANSPOSE4x8B_LOAD PASS8ROWS(pix0q, pixq, strideq, r3strideq) 
    CHROMA_DEBLOCK_BODY 8 
    TRANSPOSE8x4B_STORE PASS8ROWS(pix0q, pixq, strideq, r3strideq) 
    RET 

Так я полагаю, что cglobal, кажется, сделать некоторые имя коверкая, так что я смотрю его в другой включаемые файлы в Я считаю, что макрос внутри cglobal макросъемки (x86util.asm):

%macro CAT_UNDEF 2 
    %undef %1%2 
%endmacro 

%macro DEFINE_ARGS 0-* 
    %ifdef n_arg_names 
     %assign %%i 0 
     %rep n_arg_names 
      CAT_UNDEF arg_name %+ %%i, q 
      CAT_UNDEF arg_name %+ %%i, d 
      CAT_UNDEF arg_name %+ %%i, w 
      CAT_UNDEF arg_name %+ %%i, h 
      CAT_UNDEF arg_name %+ %%i, b 
      CAT_UNDEF arg_name %+ %%i, m 
      CAT_UNDEF arg_name %+ %%i, mp 
      CAT_UNDEF arg_name, %%i 
      %assign %%i %%i+1 
     %endrep 
    %endif 

    %xdefine %%stack_offset stack_offset 
    %undef stack_offset ; so that the current value of stack_offset doesn't get baked in by xdefine 
    %assign %%i 0 
    %rep %0 
     %xdefine %1q r %+ %%i %+ q 
     %xdefine %1d r %+ %%i %+ d 
     %xdefine %1w r %+ %%i %+ w 
     %xdefine %1h r %+ %%i %+ h 
     %xdefine %1b r %+ %%i %+ b 
     %xdefine %1m r %+ %%i %+ m 
     %xdefine %1mp r %+ %%i %+ mp 
     CAT_XDEFINE arg_name, %%i, %1 
     %assign %%i %%i+1 
     %rotate 1 
    %endrep 
    %xdefine stack_offset %%stack_offset 
    %assign n_arg_names %0 
%endmacro 

Это, кажется, делает это имя коверкая и добавьте q в конце аргументов. Однако я не понимаю, почему существует несколько строк директив %undef, и в этой функции используется только имя переменной с суффиксом q. Он также, кажется, добавляет число в конце, но по какой-то причине я не вижу его в другом asm-файле.

Что мне здесь не хватает?

ответ

2

Макрос DEFINE_ARGS определяет число однострочных макросов, предназначенных для использования в аргументах функции, которую вводит макрос cglobal. Так, например, если foo дается как имя первого аргумента, то DEFINE_ARGS создает следующие устанавливает:

%xdefine fooq r0q 
%xdefine food r0d 
%xdefine foow r0w 
%xdefine fooh r0h 
%xdefine foob r0b 
%xdefine foom r0m 
%xdefine foomp r0mp 

суффиксы представляют, как предполагается аргумент доступен. В первых пяти суффиксах q, d, w, h,, b указаны размер: указатель (четырехзначное слово или двойное слово), двойное слово, слово, байт и байт соответственно. Суффикс h указывает, что байт является высокой частью 16-битного значения. Суффикс m обращается к аргументу как операнд памяти неуказанного размера, а суффиксы mp обращаются к нему как операнд памяти размера указателя.

rNx имена, которые определяются этим макросом макроса, как сами макросы. Они расширяются до регистра или ячейки памяти для суффиксов m и mp, где хранится аргумент N. Поэтому при сборке для 64-разрядной Windows, макросов для первого аргумента эффективно:

%define r0q rcx 
%define r0d ecx 
%define r0w cx 
%define r0h ch 
%define r0b cl 
%define r0m ecx 
%define r0mp rcx 

Обратите внимание, что, так как 64-разрядное соглашение о вызовах для Windows проходит первый аргумент в регистре (RCX) нет никакой ячейки памяти что соответствует этому аргументу.

При создании 32-разрядных нацелен на первый аргумент rNx макросы конца получать определенный как это:

%define r0q eax 
%define r0d eax 
%define r0w ax 
%define r0h ah 
%define r0b al 
%define r0m [esp + stack_size + 4] 
%define r0mp dword [esp + stack_size + 4] 

r0q макро в этом случае только получает доступ к 32-битовый регистр, так как 64-битных регистров недоступны в 32-битном коде. Поскольку этот первый аргумент передается в стеке при выполнении 32-битных условных соглашений, код пролога, сгенерированный макросом cglobal, загружает первый аргумент в EAX.

Очевидно, что код, который вы видели, который использует эти макросы аргументов, имеет доступ только к аргументам размера указателя, поэтому вы видите только суффиксы q.

Назначение строк% undef в начале макроса DEFINE_ARGS заключается в том, чтобы определить макросы аргументов, которые были определены предыдущим вызовом DEFINES_ARGS. В противном случае они останутся определяемыми в текущей функции. Имена аргументов предыдущей функции хранятся в одной строке макросов с именем arg_name N.

Пожалуйста, не следуйте примеру, указанному кодом, который вы читаете. Они по существу создают производный и уникальный язык программирования, который действительно понят только авторам макросов. Это также не самый эффективный способ делать вещи. Если бы я писал этот код, я бы использовал C/C++ и его векторные свойства. Это оставило бы все различия между 32-битными и 64-битными, Windows и Linux компилятором, которые могли бы генерировать лучший код, чем эти макросы.

+0

Хорошо, что вся макроса, которая позаботится об обработке стека для вас, довольно аккуратная из того, что я видел. Кажется, что это намного лучше, чем встроенная сборка (и все проблемы с переносимостью, которые возникают с ней), хотя я согласен, если производительность не является проблемой, в которой нет необходимости. Большое вам спасибо за разъяснение всего этого, я хочу, чтобы потомки они могли включить ваш ответ в комментарии. – meneldal

Смежные вопросы