Author Topic: Macro to find nearest return instruction  (Read 559 times)

Offline zcap

  • Jr. Member
  • *
  • Posts: 2
Macro to find nearest return instruction
« on: June 28, 2022, 10:24:52 PM »
Hi all.

I was wondering if it is at all possible to use the NASM macro language to find the "nearest" RET instructions to a particular address? For example, I frequently use simple conditional return macros but in some cases, where there might be multiple conditional return macros within a 128 byte window of a ret instruction, I'd rather not have each conditional return macro define it's own ret instruction, but instead have them share the same return instruction.
As part of my conditional return macros, I have a "return" macro which wraps the ret instruction and adds a label which points to the instruction. This label is called %%_ret.
My idea is to search the 128 byte window for a regular expression which ends with a _ret label, from $ inside the conditional return macro, but I am not sure if the NASM preprocessor accept's regexes. Nevertheless, I thought I'd ask here. Perhaps I am approaching it the wrong way.
Either way, any help would be appreciated.

Many thanks,
zcap

PS. Here is an example of the situation:
   
myProc:
    call proc1
    retc    ;Return if carry
    push rax
    movzx eax, word [var1]
    cmp ax, word [rdi + myStruc.localLabel1]
    pop rax
    rete
    mov al, 6
    stc
    return


Here are my macro definitions for the retc, rete and return macros:

%macro return 0
%%_ret:
    ret
%endmacro

%macro cret 1
    j%-1 short %%a
    return
%%a:
%endmacro

%macro retc 0
cret c
%endmacro

%macro rete 0
cret e
%endmacro


Offline zcap

  • Jr. Member
  • *
  • Posts: 2
Re: Macro to find nearest return instruction
« Reply #1 on: June 28, 2022, 11:27:32 PM »
Think I solved it, though predictably, it works by looking backwards in the file for the previous ret instruction.
This seemed to produce the deisred output in the listing file:


%macro return 0
%%_ret:
    ret
%assign retOff %%_ret-$$  ;Get offset into segment of %%_ret
%endmacro

%macro cret 1
%%_base:
%assign baseVar %%_base-$$ ;Get offset into segment of %%_base
    %ifdef retOff
    %if (baseVar - retOff <= 126) && (baseVar > retOff)
    j%+1 short (retOff+section.<currentSegment>.vstart)
    %else
    j%-1 short %%a
    return
%%a:
    %endif
    %else
    j%-1 short %%a
    return
%%a:
    %endif
%endmacro


section.<currentSegment>.vstart is needed in multi segment programs which use segment relocation at runtime as the offsets are worked out relative to the file it seems and not their loacations in memory. I am now trying to work out how to "dynamically" work out the current segment and get that segment's virtual start address. In any case, for most tasks, it is not needed.

Comments and suggestions are welcome!
« Last Edit: June 29, 2022, 01:06:01 PM by zcap »