使用nasm宏组合一些代码

时间:2018-05-25 03:02:25

标签: performance assembly optimization x86 nasm

考虑一个nasm宏,用于在调用它时注入一些程序集,在这种情况下测试传递的参数是否等于42:

%macro special_handler_if_42 1
    cmp  42, %1
    jne  %%skip
    ; some additional assembly to handle the %1 == 42 case
    push %1
    push 42
    call some_func
%%skip:
%endmacro

如果 相等,我们会执行一些额外的操作,否则我们只需继续宏后面的代码。到目前为止,非常好。

现在我想以功能相同的方式编写宏,除了&#34;等于42&#34;情况,恰好是非常罕见的,被移动&#34;脱离&#34;,以便直通(无跳转)情况是默认情况,类似于(现在不以宏形式显示):< / p>

    cmp  42, rax
    je  equals_42
jump_back:
    ; the rest of the code that follows the macro
    ret

    ; somewhere outside the current function
equals_42:
    push rax
    push 42
    call some_func
    jmp jump_back

这在执行时更有效,也可能节省i-cache空间。我不确定如何编写具有非局部效果的宏。欢迎提示。

1 个答案:

答案 0 :(得分:3)

如果您不介意将宏拆分为两个宏,一个执行测试,一个处理断言,那么您可以使用NASM's context stack

我想象了一个assert_XXX形式的宏系统,它们都非常相似并且执行特定的测试。
超出函数末尾的单个assertions_handler将生成所需的任何处理程序。

由于此系统使用上下文堆栈,因此您应该能够多次使用它来执行不同的功能 基本上,每个assert_XXX函数都会在堆栈上推送一个上下文,assertions_handler将全部消耗它们。

assert_XXX还将定义上下文本地宏argX以将其参数传递给处理程序,因此无需对任何内容进行硬编码。

BITS 64

%macro assert_not_equal 2
    ;Create and push a new context (The name is optional but goodpractice)
    %push assert_equal_ctx

    %define %$arg1 %1
    %define %$arg2 %2

    cmp  %1, %2
    je  %$handler

%$jump_back:

%endmacro


%macro assert_greater 2
    %push assert_greater_ctx

    %define %$arg1 %1
    %define %$arg2 %2

    cmp  %1, %2
    jbe  %$handler

%$jump_back:

%endmacro

%macro assertions_handler 0

    %rep 1000

        %ifctx assert_equal_ctx

        %$handler:
            push %$arg1
            push %$arg2
            call somefunc
            jmp %$jump_back

            %pop assert_equal_ctx

        %elifctx assert_greater_ctx

        %$handler:
            push %$arg1
            push %$arg2
            call somefunc2

            %pop assert_greater_ctx

        %else

            %exitrep

        %endif
    %endrep
%endmacro


;
;TEST TEST TEST TEST TEST TEST TEST TEST
; 


assert_not_equal rax, 5

nop
nop
nop

assert_greater rax, 8

nop
nop
nop

ret

assertions_handler

;
; Handler functions
;

somefunc:
    ret

somefunc2:
    ret

每个函数的最大断言数设置为1000,您可以将其增加到2 62