flat assembler
Message board for the users of flat assembler.
 Home   FAQ   Search   Register 
 Profile   Log in to check your private messages   Log in 
flat assembler > Macroinstructions > fasmg as preprocessor

Goto page 1, 2, 3  Next
Author
Thread Post new topic Reply to topic
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
fasmg as preprocessor
Hi all,

how can i use fasmg as a preprocessor , so that , it will read the source file and start manipulates the source code , passes the unknown stuff to the output and treats the macros the defined?
Post 17 Feb 2017, 11:00
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6606
Location: Kraków, Poland
fasmg has no separate preprocessor, so it is very hard to untangle it in any way that would be practical. For example you could catch lines containing undefined macros with something like:

Code:
struc (label? decl&
        db `label,' ',`decl,13,10
end struc

But this would not catch the instructions that are actually defined internally, like DB or even SECTION, and I suspect that would actually want to catch them too - in fact this may even not be a well-defined problem. Which instructions do we want to treat as "defined" and which ones to pass through?
Post 17 Feb 2017, 13:16
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6606
Location: Kraków, Poland
I made an interesting experiment based on the trick I once mentioned, which uses the fact that namespace of local symbols in a macro has no parent namespace, so inside such namespace there are no instructions defined. The following snippet uses this clean namespace and generates the "instruction gates" only for the instructions which we want to have "preprocessed", like MACRO or ITERATE:

Code:

macro preprocess

        local Preprocessor

        macro gate list&
                iterate instrlist
                        macro Preprocessor.instr?! args&
                                esc instr args
                        end macro
                end iterate
        end macro
        gate end,macro,iterate,irp,repeat,rept,while,break,indx,if,else,match,rmatch,rawmatch,postpone

        macro make_interceptor instr
                struc (label? decl&
                        instr `label,' ',`decl,13,10
                end struc
        end macro
        make_interceptor db

        namespace Preprocessor

        postpone
                end namespace
        end postpone

end macro

preprocess


; The source to preprocess:

macro invoke name,args&
        iterate arg,args
                indx %%-%+1
                push arg
        end iterate
        call [name]
end macro

format PE GUI
entry start

section '.text' code readable executable

  start:

        invoke  MessageBoxA,0,_message,_caption,0

        invoke  ExitProcess,0

section '.data' data readable writeable

  _caption db 'Win32 assembly program',0
  _message db 'Hello World!',0

section '.idata' import data readable writeable

  dd 0,0,0,RVA kernel_name,RVA kernel_table
  dd 0,0,0,RVA user_name,RVA user_table
  dd 0,0,0,0,0

  kernel_table:
    ExitProcess dd RVA _ExitProcess
    dd 0
  user_table:
    MessageBoxA dd RVA _MessageBoxA
    dd 0

  kernel_name db 'KERNEL32.DLL',0
  user_name db 'USER32.DLL',0

  _ExitProcess dw 0
    db 'ExitProcess',0
  _MessageBoxA dw 0
    db 'MessageBoxA',0

The output looks like:

Code:
format PE GUI
entry start
section '.text' code readable executable
start :
push 0
push _caption
push _message
push 0
call [MessageBoxA]
push 0
call [ExitProcess]
section '.data' data readable writeable
_caption db 'Win32 assembly program',0
_message db 'Hello World!',0
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,RVA user_name,RVA user_table
dd 0,0,0,0,0
kernel_table :
ExitProcess dd RVA _ExitProcess
dd 0
user_table :
MessageBoxA dd RVA _MessageBoxA
dd 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
_ExitProcess dw 0
db 'ExitProcess',0
_MessageBoxA dw 0
db 'MessageBoxA',0

This still is probably not practical, but an interesting exercise nonetheless.
Post 17 Feb 2017, 13:28
View user's profile Send private message Visit poster's website Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
thanks Tomasz very much.

I will study it carefully.
Post 17 Feb 2017, 15:43
View user's profile Send private message Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
Hi Tomasz

when testing that macro with something like this

Code:

/******
  tisting
*****/

 some code

// this is c comment

 some code




it does not recognize the c comment , so how to pass them to output file?

thanks

Edited
also i have a simple request , can fasmg treats ; "simecolom" as just a char and
allowing asm comment from macro?
Post 19 Feb 2017, 15:38
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6606
Location: Kraków, Poland
I think what you are looking for here is a customized tool based on fasmg. In fact, the changes you'd need may be relatively easy to make on fasmg sources. You would need to remove all the instructions you don't need from the TABLES.INC, remove semicolon processing from READER.INC (around the "skip_comment" label) and add a special handling in ASSEMBLER.INC at "unrecognized_instruction" label to pass the content of such line to the output (this one might be a bit harder to do). Thought I'm still not sure if that would be enough for you purpose, I have a feeling that you are trying to do something risky in principle.
Post 19 Feb 2017, 16:07
View user's profile Send private message Visit poster's website Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
yes , you are correct.

my goal is making fasmg as a tool that develop an old language and allowing insert modern asm instruction in old code via fasmg macros and the db directive.

do you think that be possible or not ?
Post 19 Feb 2017, 18:52
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6606
Location: Kraków, Poland

emil wrote:
yes , you are correct.

my goal is making fasmg as a tool that develop an old language and allowing insert modern asm instruction in old code via fasmg macros and the db directive.

do you think that be possible or not ?

If you formulate it like this, it looks like an entirely different problem. I think the correct approach would be to detect some markup in the source text that would show where there are assembly instructions inserted, and assembling only these pieces of text.

I tried to patch up something quickly to demonstrate how you could use EVAL to do something like that:

Code:

include '80386.inc'

virtual at 0
        HEX_digits:: db '0123456789ABCDEF'
end virtual

macro assemble text
        local assembled
        virtual at 0
                assembled:: use32
                eval text
                assembled.length = $
        end virtual
        repeat assembled.length
                load assembled.byte:1 from assembled:%-1
                load assembled.digit:1 from HEX_digits:assembled.byte shr 4
                db assembled.digit
                load assembled.digit:1 from HEX_digits:assembled.byte and 0Fh
                db assembled.digit
                db ' '
        end repeat
end macro

virtual at 0
 source:: file 'source.txt'
 .length = $
end virtual

position = 0
block_start = -1

while position < source.length
        if position < source.length - 1
                load signature:2 from source:position
        else
                load signature:1 from source:position
        end if
        if signature = '<@' & block_start < 0
                block_start = position + 2
                position = position + 2
                db 'Bytes: '
        else if signature = '@>' & block_start > 0
                load text:position-block_start from source:block_start
                assemble text
                position = position + 2
                block_start = -1
        else
                if block_start < 0
                        db signature and 0FFh
                end if
                position = position + 1
        end if
end while

This snippets loads the contents of "source.txt" file and looks for blocks of assembly instructions marked with <@ and @>, assembles these blocks and replaces them with hexadecimal representation of the generated bytes. For example this file:

Code:

// this can be any text file

assembly routine {
<@

 mov    eax,1
 ret

@>
}

becomes the following after processing:

Code:

// this can be any text file

assembly routine {
BytesB8 01 00 00 00 C3

}

You can tweak it to generate a text representation of the assembled code that you need, and you could use different markup. And if the markup sequences would be longer, implementing a Boyer-Moore-Hornspool algorithm might not be a bad idea (you could use and old implementation for fasm 1 as a starting point).
Post 19 Feb 2017, 22:31
View user's profile Send private message Visit poster's website Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
thank you again,

actually i was using block detecting , when developing SphinxC-- , just as you mintioned above.

but , i am newbee with fasmg.

I will try it , finally , i think fasmg will be very strong tool that achieves many verity desires.
Post 20 Feb 2017, 06:33
View user's profile Send private message Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
while i testing the last macro, i modified it so that allowing inline line of text instead of block.

here is my modification


Code:

include '80386.inc' 

virtual at 0 
        HEX_digits:: db '0123456789ABCDEF' 
end virtual 

macro assemble text 
        local assembled 
        virtual at 0 
                assembled:: use32 
                eval text 
                assembled.length = $ 
        end virtual 
        repeat assembled.length 
                load assembled.byte:1 from assembled:%-1 
                load assembled.digit:1 from HEX_digits:assembled.byte shr 4 
                db assembled.digit 
                load assembled.digit:1 from HEX_digits:assembled.byte and 0Fh 
                db assembled.digit 
                db ' ' 
        end repeat 
end macro 

virtual at 0 
 source:: file 'test2.asm' ; open the source.txt file 
 .length = $                ; get the length of  file
end virtual 

position = 0 
block_start = -1 
inline = -1

while position < source.length 
        if position < source.length - 1 
                load signature:2 from source:position ;read from source with word size
        else 
                load signature:1 from source:position ;if we at the end read the last char 
        end if 
        if signature = '<@' & block_start < 0  ;search for start block
                block_start = position + 2     ;skip the block mrak and point to the block start
                position = position + 2        ;update reading postion of source
                db 'Bytes: '                   ;print Bytes: text
        else if signature = '@>' & block_start > 0 ;check for block end
                load text:position-block_start from source:block_start ;get the entire block into text variable
                assemble text             ; pass the block to assemble macro
                position = position + 2   ; update reading postion of source
                block_start = -1          ; allow to search for next block
        else if signature and 0FFh  = '!' & block_start < 0 & inline < 0
                inline = position + 1
                position = position + 1
        else if signature and 0FFh  = 10 & block_start < 0 & inline = 0
                load text:position-inline from source:inline
                assemble text
                position = position + 1
                inline = -1
        else 
                if block_start < 0        ; we are not inside the block so pass the char to output
                        db signature and 0FFh 
                end if 
                position = position + 1   ; update reading postion of source
        end if 
end while




and here is the test example

Code:

// this can be any text file 

assembly routine { 
<@ 

 mov    eax,1 
 ret 

@

! mov    eax,2 

}




but it does not work as expected

here is the output


Code:

// this can be any text file 

assembly routine { 
BytesB8 01 00 00 00 C3  

 mov    eax,2 

}




any help pleas?
Post 20 Feb 2017, 15:29
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6606
Location: Kraków, Poland
Where you have "& inline = 0" condition, it should be "& inline > 0".
Post 20 Feb 2017, 16:54
View user's profile Send private message Visit poster's website Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
yes , Tomasz

here the correct one

Code:

include '80386.inc' 

virtual at 0 
        HEX_digits:: db '0123456789ABCDEF' 
end virtual 

macro assemble text 
        local assembled 
        virtual at 0 
                assembled:: use32 
                eval text 
                assembled.length = $ 
        end virtual 
        repeat assembled.length 
                load assembled.byte:1 from assembled:%-1 
                load assembled.digit:1 from HEX_digits:assembled.byte shr 4 
                db assembled.digit 
                load assembled.digit:1 from HEX_digits:assembled.byte and 0Fh 
                db assembled.digit 
                db ' ' 
        end repeat 
end macro 

virtual at 0 
 source::          ;this is a global lable 
  file 'test2.asm' ; open the source.txt file 
 .length = $       ; get the length of source.txt file
end virtual 

position = 0 
block_start = -1 
inline = -1

while position < source.length 
        if position < source.length - 1 
                load signature:2 from source:position ;read from source with word size
        else 
                load signature:1 from source:position ;if we at the end read the last char 
        end if 
        if signature = '<@' & block_start < 0  ;search for start block
                block_start = position + 2     ;skip the block mrak and point to the block start
                position = position + 2        ;update reading postion of source
                db 'Bytes: db '                   ;print Bytes: text
        else if signature = '@>' & block_start > 0 ;check for block end
                load text:position-block_start from source:block_start ;get the entire block into text variable
                assemble text             ; pass the block to assemble macro
                position = position + 2   ; update reading postion of source
                block_start = -1          ; allow to search for next block
        else if signature and 0FFh  = '!' & block_start < 0 & inline < 0
                inline = position + 1
                position = position + 1
                db ' db '     
        else if signature and 0FFh  = 10 & block_start < 0 & inline >= 0
                load text:position-inline from source:inline
                assemble text
                position = position + 1
                inline = -1
        else 
                if block_start < 0  & inline < 0     ; we are not inside the block so pass the char to output
                        db signature and 0FFh 
                end if 
                position = position + 1   ; update reading postion of source
        end if 
end while


Post 20 Feb 2017, 17:30
View user's profile Send private message Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
consider the next example


Code:

// this can be any text file 

assembly routine { 

msg
       db 'out of block',0

<@ 
  jmp lab
  
  txt
       db 'fasmg is very powerful',0

lab:

 mov    eax,txt
 ret 

@

! mov    eax,2 

}




is there a way to reach to msg label from inside the block?

i can push the msg address outside the block and then later pop the address from inside block , but this is not a good solution.

also how can we call a function from inside a block?
Post 20 Feb 2017, 18:14
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6606
Location: Kraków, Poland
Now this is something that requires a bit different approach. Here's a modified version of my previous example:

Code:
include '80386.inc' 

virtual at 0 
        HEX_digits:: db '0123456789ABCDEF' 
end virtual

macro hex? value
        local number,digit
        number = value
        repeat 1 + (bsr number shr 2)
                load digit:1 from HEX_digits:number shr ((%%-%)*4and 0Fh
                if %=1 & digit > '9'
                        dbx 1:'0'
                end if
                dbx 1digit
        end repeat
        dbx 1'h'
end macro

macro db? values&
        dbx 1:'db '
        iterate valuevalues
                if % > 1
                        dbx 1:','
                end if
                hex value
        end iterate
        dbx 1:13,10
end macro

macro dw? values&
        dbx 1:'dw '
        iterate valuevalues
                if % > 1
                        dbx 1:','
                end if
                hex value
        end iterate
        dbx 1:13,10
end macro

macro dd? values&
        dbx 1:'dd '
        iterate valuevalues
                if % > 1
                        dbx 1:','
                end if
                hex value
        end iterate
        dbx 1:13,10
end macro

virtual at 0 
 source:: file 'source.txt' 
 .length = $ 
end virtual 

position = 0 
block_start = -1 

while position < source.length 
        if position < source.length - 1 
                load signature:2 from source:position 
        else 
                load signature:source.length-position from source:position
        end if 
        if signature = '<@' & block_start < 0 
                block_start = position + 2 
                position = position + 2 
        else if signature = '@>' & block_start > 0 
                load text:position-block_start from source:block_start 
                eval text
                position = position + 2 
                block_start = -1 
        else 
                if block_start < 0 
                        dbx 1:signature and 0FFh
                end if 
                position = position + 1 
        end if 
end while

This time we do not need a special "assemble" macro, we just redefine DB/DW/DD directives so that when instruction macros use them to generate opcodes, we instead generate text of these directives.

Now we need to detect when a value is not a local one. To make the problem easier (at least initially), let's add the "extrn" macro there to mark the names of symbols that we want to use from the "outside". This time we modify DD macro to detect such external symbol. I store the name of the symbol in the metadata of ELEMENT, so that DD can the easily extract names for all the variable terms. We also need to generate a label for every block, so that we can express the offsets with relation to the beginning of the block:

Code:
include '80386.inc'

macro extrn? names
        iterate namenames 
                element name : `name 
        end iterate 
end macro 

virtual at 0 
        HEX_digits:: db '0123456789ABCDEF'  
end virtual 

macro hex? value 
        local number,digit 
        number = value 
        if number < 0 
                dbx 1:'-' 
                number = - number 
        end if 
        repeat 1 + (bsr number shr 2
                load digit:1 from HEX_digits:number shr ((%%-%)*4and 0Fh 
                if %=1 & digit > '9' 
                        dbx 1:'0' 
                end if 
                dbx 1digit 
        end repeat 
        dbx 1'h' 
end macro 

macro db? values&
        local position,byte
        position = $
        iterate valuevalues
                byte = value
                if % = 1
                        dbx 1:'db '
                else
                        dbx 1:','
                end if 
                hex byte
                position = position + 1
                ; org position
        end iterate 
        dbx 1:13,10
        org position
end macro

macro dw? values&
        local position,word
        position = $
        iterate valuevalues
                word = value
                if % = 1
                        dbx 1:'dw '
                else
                        dbx 1:','
                end if 
                hex word
                position = position + 2
                ; org position
        end iterate
        dbx 1:13,10 
        org position
end macro

macro dd? values&
        local position,poly
        position = $
        iterate valuevalues
                poly = value
                if % = 1
                        dbx 1:'dd '
                else
                        dbx 1:','
                end if 
                if poly relativeto 0
                        hex poly 
                else 
                        repeat elementsof poly
                                if poly scale % < 0
                                        dbx 1:'-' 
                                        if - poly scale %  > 1
                                                hex - poly scale %
                                                dbx 1:'*' 
                                        end if 
                                else 
                                        if % > 1 
                                                dbx 1:'+' 
                                        end if 
                                        if poly scale % > 1
                                                hex poly scale %
                                                dbx 1:'*' 
                                        end if 
                                end if 
                                dbx 1:string poly metadata %
                        end repeat 
                        if poly scale 0
                                if poly scale 0 > 0
                                        dbx 1:'+' 
                                end if 
                                hex poly scale 0
                        end if 
                end if 
                position = position + 4
                ; org position
        end iterate
        dbx 1:13,10 
        org position
end macro

virtual at 0 
 source:: file 'source.txt'  
 .length = $  
end virtual  

position = 0  
block_start = -1 
block_number = 0 

macro assemble id,text 
        local output,name,base 
        output dbx 1:'block_' 
        hex id 
        load name:$-output from output 
        dbx 1:':',13,10 
        element base : name 
        org base 
        use32 
        eval text 
end macro 

while position < source.length  
        if position < source.length - 1  
                load signature:2 from source:position  
        else  
                load signature:source.length-position from source:position 
        end if  
        if signature = '<@' & block_start < 0  
                block_start = position + 2  
                position = position + 2  
        else if signature = '@>' & block_start > 0  
                load text:position-block_start from source:block_start 
                block_number = block_number + 1 
                assemble block_number,text 
                position = position + 2  
                block_start = -1  
        else  
                if block_start < 0  
                        dbx 1:signature and 0FFh 
                end if  
                position = position + 1  
        end if  
end while

This variant can treat the following text:

Code:
// Demonstration of a pre-assembly of blocks of text

<@

        extrn msg,print

        mov     eax,msg+1
        call    print
        ret

@>

and generates the following output:

Code:
// Demonstration of a pre-assembly of blocks of text

block_1h:
db 0B8h
dd msg+1h
db 0E8h
dd print-block_1h-0Ah
db 0C3h



Last edited by Tomasz Grysztar on 21 Feb 2017, 14:59; edited 5 times in total
Post 20 Feb 2017, 19:09
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6606
Location: Kraków, Poland
The automatic detection of undefined symbols (without "extrn" declarations) is possible, but very tricky. It requires interception of all the arguments passed to x86 instructions and scanning them for undefined names. We can do it by overloading the "x86.parse_operand_value" macro:

Code:
virtual at 0
        Name_XLAT:: 
        repeat 256c:0 
                if (c >= '0' & c <= '9') \ 
                   | c = '+' | c = '-' | c = '/' | c = '*' | c = '=' | c = '<' | c = '>' | c = '(' | c = ')' \ 
                   | c = '[' | c = ']' | c = '{' | c = '}' | c = ':' | c = '?' | c = '!' | c = ',' | c = '.' \ 
                   | c = '|' | c = '&' | c = '~' | c = '#' | c = '`' | c = '\' | c = '"' | c = "'" 
                        db 0 
                else 
                        db 1 
                end if 
        end repeat 
end virtual 

macro x86.parse_operand_value ns,op   
        local buffer,is_name,auto_extrn  
        define buffer op:   
        while 1   
                match sym tailbuffer   
                        define buffer tail   
                        load is_name:1 from Name_XLAT:`sym and 0FFh   
                        if is_name  
                                if defined auto_extrn.sym & (auto_extrn.sym | ~ defined sym
                                        extrn sym  
                                        auto_extrn.sym := 1 
                                else if ~ defined sym  
                                        auto_extrn.sym := 0 
                                end if  
                        end if   
                else   
                        break   
                end match   
        end while   
        x86.parse_operand_value ns,op   
end macro

You can just add this macro to the above samples (just after the "extrn" macro) to get the automatic detection of undefined symbols. It might be slow, though.

PS Thank you for bringing this up! I did not even realize myself that such thing might be possible.


Last edited by Tomasz Grysztar on 21 Feb 2017, 17:01; edited 2 times in total
Post 20 Feb 2017, 19:48
View user's profile Send private message Visit poster's website Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
the thanks must go to you ,

you are very smart person, especially the last trick.

i will try it , will let you know the news.
Post 21 Feb 2017, 05:54
View user's profile Send private message Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
i got this error message

Quote:

flat assembler version g.hp0ga
E:\fasmg\forum\preprocessor\pp2.inc [183]:
assemble block_number,text
macro assemble [9] eval [5] macro add [1] macro basic_instruction [29] macro store_instruction [23] macro db [0]
Processed: db 83h, @dest.mod shl 6 + 0 shr 3 shl 3 + @dest.rm
Error: extra characters on line.



when testing this example

Code:

// Demonstration of a pre-assembly of blocks of text 

#include <stdio>

charmsg = "mix c & fasm is promising";

void main()
{
    
<@         

        push     msg 
        call    _puts 
        add     esp , 4

@>

   system("pause");
}




any help please?
Post 21 Feb 2017, 14:54
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6606
Location: Kraków, Poland
Oh, sorry, that's because of my typo. Instead of "macro db? values?" it should have been "macro db? values&", the same in two other places. I edited my post to fix it.
Post 21 Feb 2017, 15:00
View user's profile Send private message Visit poster's website Reply with quote
emil



Joined: 16 Dec 2003
Posts: 70
Location: egypt
thanks Tomasz,

i have an other issue , i added the inline code to yours , but it nothing added.

Code:

position = 0   
block_start = -1  
block_number = 0  
inline = -1

macro assemble id,text  
        local output,name,base  
        output dbx 1:'block_'  
        hex id  
        load name:$-output from output  
        dbx 1:':',13,10  
        element base : name  
        org base  
        use32  
        eval text  
end macro  

while position < source.length   
        if position < source.length - 1   
                load signature:2 from source:position   
        else   
                load signature:source.length-position from source:position  
        end if   
        if signature = '<@' & block_start < 0   
                block_start = position + 2   
                position = position + 2   
        else if signature = '@>' & block_start > 0   
                load text:position-block_start from source:block_start  
                block_number = block_number + 1  
                assemble block_number,text  
                position = position + 2   
                block_start = -1  
        else if signature and 0FFh  = '!' & block_start < 0 & inline < 0
                inline = position + 1
                position = position + 1
        else if signature and 0FFh  = 10 & block_start < 0 & inline > 0
                load text:position-inline from source:inline
                block_number = block_number + 1
                assemble block_number,text 
                position = position + 1
                inline = -1         
        else   
                if block_start < 0   & inline < 0    
                        dbx 1:signature and 0FFh  
                end if   
                position = position + 1   
        end if   
end whil




edited
sorry after applying your last fix , it works well.
Post 21 Feb 2017, 15:17
View user's profile Send private message Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6606
Location: Kraków, Poland
I have tried it and seems to work correctly:

Code:
include '80386.inc'

macro extrn? names&  
        iterate namenames  
                element name : `name  
        end iterate  
end macro

virtual at 0
        Name_XLAT::  
        repeat 256c:0  
                if (c >= '0' & c <= '9') \  
                   | c = '+' | c = '-' | c = '/' | c = '*' | c = '=' | c = '<' | c = '>' | c = '(' | c = ')' \  
                   | c = '[' | c = ']' | c = '{' | c = '}' | c = ':' | c = '?' | c = '!' | c = ',' | c = '.' \  
                   | c = '|' | c = '&' | c = '~' | c = '#' | c = '`' | c = '\' | c = '"' | c = "'"  
                        db 0  
                else  
                        db 1  
                end if  
        end repeat  
end virtual  

macro x86.parse_operand_value ns,op  
        local buffer,is_name,auto_extrn 
        define buffer op:  
        while 1  
                match sym tailbuffer  
                        define buffer tail  
                        load is_name:1 from Name_XLAT:`sym and 0FFh  
                        if is_name 
                                if defined auto_extrn.sym & (auto_extrn.sym | ~ defined sym)
                                        extrn sym 
                                        auto_extrn.sym := 1
                                else if ~ defined sym 
                                        auto_extrn.sym := 0
                                end if 
                        end if  
                else  
                        break  
                end match  
        end while  
        x86.parse_operand_value ns,op  
end macro

virtual at 0  
        HEX_digits:: db '0123456789ABCDEF'   
end virtual  

macro hex? value  
        local number,digit  
        number = value  
        if number < 0  
                dbx 1:'-'  
                number = - number  
        end if  
        repeat 1 + (bsr number shr 2)  
                load digit:1 from HEX_digits:number shr ((%%-%)*4and 0Fh  
                if %=1 & digit > '9'  
                        dbx 1:'0'  
                end if  
                dbx 1digit  
        end repeat  
        dbx 1'h'  
end macro  

macro db? values
        local position,byte 
        position = $ 
        iterate valuevalues 
                byte = value 
                if % = 1 
                        dbx 1:'db ' 
                else 
                        dbx 1:',' 
                end if  
                hex byte 
                position = position + 1 
                ; org position 
        end iterate  
        dbx 1:13,10 
        org position 
end macro 

macro dw? values
        local position,word 
        position = $ 
        iterate valuevalues 
                word = value 
                if % = 1 
                        dbx 1:'dw ' 
                else 
                        dbx 1:',' 
                end if  
                hex word 
                position = position + 2 
                ; org position 
        end iterate 
        dbx 1:13,10  
        org position 
end macro 

macro dd? values
        local position,poly 
        position = $ 
        iterate valuevalues 
                poly = value 
                if % = 1 
                        dbx 1:'dd ' 
                else 
                        dbx 1:',' 
                end if  
                if poly relativeto 0 
                        hex poly  
                else  
                        repeat elementsof poly 
                                if poly scale % < 0 
                                        dbx 1:'-'  
                                        if - poly scale %  > 1 
                                                hex - poly scale % 
                                                dbx 1:'*'  
                                        end if  
                                else  
                                        if % > 1  
                                                dbx 1:'+'  
                                        end if  
                                        if poly scale % > 1 
                                                hex poly scale % 
                                                dbx 1:'*'  
                                        end if  
                                end if  
                                dbx 1:string poly metadata % 
                        end repeat  
                        if poly scale 0 
                                if poly scale 0 > 0 
                                        dbx 1:'+'  
                                end if  
                                hex poly scale 0 
                        end if  
                end if  
                position = position + 4 
                ; org position 
        end iterate 
        dbx 1:13,10  
        org position 
end macro 

virtual at 0  
 source:: file 'source.txt'   
 .length = $   
end virtual   


position = 0    
block_start = -1   
inline = -1
block_number = 0

macro assemble id,text   
        local output,name,base   
        output dbx 1:'block_'   
        hex id   
        load name:$-output from output   
        dbx 1:':',13,10   
        element base : name   
        org base   
        use32   
        eval text   
end macro   

while position < source.length    
        if position < source.length - 1    
                load signature:2 from source:position    
        else    
                load signature:source.length-position from source:position   
        end if    
        if signature = '<@' & block_start < 0    
                block_start = position + 2    
                position = position + 2    
        else if signature = '@>' & block_start > 0    
                load text:position-block_start from source:block_start   
                block_number = block_number + 1   
                assemble block_number,text   
                position = position + 2    
                block_start = -1   
        else if signature and 0FFh  = '!' & block_start < 0 & inline < 0 
                inline = position + 1 
                position = position + 1 
        else if signature and 0FFh  = 10 & block_start < 0 & inline > 0 
                load text:position-inline from source:inline 
                block_number = block_number + 1
                assemble block_number,text   
                position = position + 1
                inline = -1          
        else    
                if block_start < 0   & inline < 0     
                        dbx 1:signature and 0FFh   
                end if    
                position = position + 1    
        end if    
end while

I only removed the "inline_number" variable, to avoid defining "block_1h" twice.

EDIT: OK, I see that you've got it working, too.
Post 21 Feb 2017, 15:36
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2, 3  Next

< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001-2005 phpBB Group.

Main index   Download   Documentation   Examples   Message board
Copyright © 2004-2016, Tomasz Grysztar.