flat assembler
Message board for the users of flat assembler.

flat assembler > Compiler Internals > [fasmg] Cannot generate code for jz macro

Author
Thread Post new topic Reply to topic
zhak



Joined: 12 Apr 2005
Posts: 489
Location: Belarus
Code:
macro jz? dest* local addr addr = dest - $ - 2 if addr >= -128 & addr < 128 db 01110100b db addr else err asmerr_jmp__outof_range end if end macro NNN = 127 lbl_a: db 6 jz lbl_a jz lbl_b db NNN dup 0 lbl_b:


This piece fails with error "Cannot generate code within the allowed number of passes" for NNN = 128 and 129. First I thought it's because it cannot compute lbl_b position, but it works for NNN 127 and below, as well as for NNN = 130 and above.

If not a bug, what is the exact reason so that I could forsee such behavior in the future? Thanks in advance
Post 01 Mar 2017, 16:34
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15870
Location: 162173 Ryugu
That appears to be the same problem as this:
https://board.flatassembler.net/topic.php?p=178826#178826

There is no solution unless you force the longer encoding with a small sized offset. You will have to change the macro to detect it. Maybe create a new variable that keeps track of previous passes attempts. Or perhaps change the "else" block to create two bytes of dummy data to match the other block.
Post 01 Mar 2017, 16:42
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6867
Location: Kraków, Poland
Actually in this specific case there is a simple solution. Compare how is it done in examples/x86/include/8086.inc:
Code:
macro x86.short_jump opcode,dest x86.parse_jump_operand @dest,dest if @dest.type = 'imm' & ( @dest.jump_type = 'short' | ~ @dest.jump_type ) if @dest.imm relativeto 0 & (@dest.imm < 0 | @dest.imm >= 10000h) err 'value out of range' end if db opcode if @dest.imm-($+1)<80h & @dest.imm-($+1)>=-80h db @dest.imm-($+1) else err 'relative jump out of range' db ? end if else err 'invalid operand' end if end macro
All that you need is to ensure that the offsets remain stable no matter if condition is fulfilled, so even in case of error generate the fields of appropriate length:
Code:
macro jz? dest* local addr addr = dest - $ - 2 db 01110100b if addr >= -128 & addr < 128 db addr else err asmerr_jmp__outof_range db ? end if end macro NNN = 128 lbl_a: db 6 jz lbl_a jz lbl_b db NNN dup 0 lbl_b:
Your problem was caused originally by the fact that when the relative offset was out of range, no bytes for instruction opcode were generated and therefore the relative offset shortened, leading to contradiction. You could read that statement as "if this block of code is longer than X, this instruction is not generated". When not generating an instruction causes the block to be shorter than X, that statement becomes contradictory.
Post 01 Mar 2017, 17:00
View user's profile Send private message Visit poster's website Reply with quote
zhak



Joined: 12 Apr 2005
Posts: 489
Location: Belarus
Yeah, adding a tracking variable did the trick, thanks!
Post 01 Mar 2017, 17:13
View user's profile Send private message Reply with quote
zhak



Joined: 12 Apr 2005
Posts: 489
Location: Belarus
Thank you for the explanation, Tomasz. Without it that db ? part in your macros would remain unclear
Post 01 Mar 2017, 17:19
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< 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


Copyright © 2004-2018, Tomasz Grysztar.

Powered by rwasa.