flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > Jump sequence |
Author |
|
Tomasz Grysztar 09 Sep 2021, 11:10
My article about pitfalls of optimistic multi-pass assembly actually uses this scenario as an example to discuss the problems and possible solutions.
|
|||
09 Sep 2021, 11:10 |
|
CandyMan 09 Sep 2021, 16:08
I used you macro and it works.
Code: macro jmp target { local ..after,sticky if target <> ..after | definite target | sticky = 1 jmp target sticky = 1 else sticky = 0 end if ..after: } Thanks. _________________ smaller is better |
|||
09 Sep 2021, 16:08 |
|
CandyMan 16 Sep 2021, 15:53
How to automatically replace jbe with ja and omit jmp instruction? Macro is welcome.
Code: jbe .1 ;\ jbe .1 -> ja .2 jmp .2 ;/ .1: nop .2: _________________ smaller is better |
|||
16 Sep 2021, 15:53 |
|
macomics 16 Sep 2021, 16:54
macro jmp target
{ local .addr, .offs, .test load .test word from $ - 2 if ( -16 and .test = 0x70 ) and ( $ + ( .test / 256 ) = .addr ) .test = .test xor 1 store word .test at $ - 2 else load .test word from $ - 6 load .offs dword from $ - 4 if ( -16 and .test = 0x0F80 ) and ( $ + .offs = .addr ) .test = .test xor 1 store word .test at $ - 6 else jmp target end if end if .addr: } |
|||
16 Sep 2021, 16:54 |
|
CandyMan 16 Sep 2021, 17:51
macomics wrote: macro jmp target Sorry but this not work. Code: A.asm [5]: jmp .2 ;/ jmp2.asm [6] jmp [3]: if ( -16 and .test = 0x70 ) and ( $ + ( .test / 256 ) = .addr ) processed: if(-16 and .test?2=0x70)and($+(.test?2/256)=.addr?0) error: invalid expression. _________________ smaller is better |
|||
16 Sep 2021, 17:51 |
|
macomics 16 Sep 2021, 18:31
Sorry
Quote: macro jmp target Last edited by macomics on 16 Sep 2021, 20:57; edited 3 times in total |
|||
16 Sep 2021, 18:31 |
|
CandyMan 16 Sep 2021, 20:27
Now removes the redundant jmp instruction but jumps to the wrong address. Besides, it doesn't check if the jump range is correct.
_________________ smaller is better |
|||
16 Sep 2021, 20:27 |
|
Tomasz Grysztar 16 Sep 2021, 20:46
CandyMan wrote: How to automatically replace jbe with ja and omit jmp instruction? Macro is welcome. Code: macro jbe target { local ..next define __j ..next if ~ defined ..next#.switch jbe target else ja ..next#.switch end if ..next: } macro jmp target { if defined __j & __j relativeto $ & $ - __j = 0 match _,__j \{ label _\#.switch at target \} else jmp target end if } |
|||
16 Sep 2021, 20:46 |
|
macomics 16 Sep 2021, 20:53
Tomasz Grysztar wrote:
|
|||
16 Sep 2021, 20:53 |
|
CandyMan 16 Sep 2021, 22:04
If I add the following macro, it doesn't work anymore.
I wish it would replace the first jump instruction with the opposite one and delete the next one for each condition. Code: macro ja target { local ..next define __j ..next if ~ defined ..next#.switch ja target else jbe ..next#.switch end if ..next: } _________________ smaller is better |
|||
16 Sep 2021, 22:04 |
|
macomics 16 Sep 2021, 22:12
Code: format binary as "COM" use32 macro jmp aim { local .a, .b, .c load .c word from $ - 2 if ( 0xF0 and .c = 0x70 ) & ( $ + ( .c / 256 ) = .a ) .b = aim - $ if ( .b < -127 ) | ( .b > 127 ) store word (( 0x0F and .c xor 1 ) shl 8 or 0x800F ) at $ - 2 dd .b - 4 else store word (( 0xFF and .c xor 1 ) or ( .b shl 8 )) at $ - 2 end if else load .c word from $ - 6 load .b dword from $ - 4 if ( 0xF0FF and .c = 0x800F ) & ( $ + .b = .a ) store word ( .c xor 0x0100 ) at $ - 6 store dword ( aim - $ ) at $ - 4 else jmp aim end if end if .a: } rept RC n {ja b#n jmp @f b#n: nop @@: } And yet I have completed my own version of the macro. But it will obviously take more memory from the fasm than the Tomasz Grysztar version. This is already an option typed not in the browser, but checked. It generates everything correctly, but it does not fit more than 13 uses per 64 kb. Another option allows you to generate 17 uses per 64 kb. add: Slightly reduced the required amount of memory Code: fasm ./temp.asm ./temp -m 64 -d RC=18 flat assembler version 1.73.28 (64 kilobytes memory) 3 passes, 54 bytes. fasm ./temp.asm ./temp -m 64 -d RC=19 flat assembler version 1.73.28 (64 kilobytes memory) error: out of memory. I immediately clarify. There is no length analysis logic in the macro. I hope that in 32/64 bit modes, the compiler will not start generating 16-bit conditional long jumps. Last edited by macomics on 17 Sep 2021, 09:33; edited 3 times in total |
|||
16 Sep 2021, 22:12 |
|
Tomasz Grysztar 17 Sep 2021, 07:12
CandyMan wrote: If I add the following macro, it doesn't work anymore. Code: macro ja target { local ..next define __j ..next if ~ defined ..next#.switch JA target else JBE ..next#.switch end if ..next: } Code: _ja equ ja _jbe equ jbe macro ja target { local ..next define __j ..next if ~ defined ..next#.switch _ja target else _jbe ..next#.switch end if ..next: } macro jbe target { local ..next define __j ..next if ~ defined ..next#.switch _jbe target else _ja ..next#.switch end if ..next: } Code: irp pair, ja:jbe, jbe:ja, jna:ja ;, ... { match j:n, pair \{ define j\#.p j define j\#.n n macro j target \\{ local ..next define __j ..next if ~ defined ..next\\#.switch j\#.p target else j\#.n ..next\\#.switch end if ..next: \\} \} } macro jmp target { if defined __j & __j relativeto $ & $ - __j = 0 match _,__j \{ label _\#.switch at target \} else jmp target end if } define __j ..j Also, please keep in mind that these kinds of macros may be useful in specific context, but have several potential problems that make them unsuitable for general use. I have been mostly just demonstrating a few tricks you could use (and macomics provided a couple others), but I would not recommend using them if you just copy-paste without considering and understanding what they actually do and how it applies to your case. One issue is that this "jmp" macro does not handle arguments other than plain target label. That's not a big deal, you could easily fix it with help of MATCH, filtering out the kinds of arguments that do not interest you. Another one is that when you put a label before your "jmp" instruction and use this label as a jump target, but then optimize the "jmp" away, jumping to the label will no longer have the desired effect. This is something that is very hard to solve using fasm 1 (it would be easier using fasmg, which allows to intercept labels, or even all consecutive lines). |
|||
17 Sep 2021, 07:12 |
|
CandyMan 17 Sep 2021, 11:06
Thank you for your comprehensive answer. I got what I wanted.
|
|||
17 Sep 2021, 11:06 |
|
CandyMan 17 Sep 2021, 13:25
Unfortunately, fasm cannot assemble the code below.
Code: irp pair, \ jo:jno, jno:jo, jb:jnb, jnb:jb, jc:jnc, jnc:jc, jnae:jae, jae:jnae, je:jne, jne:je, jz:jnz, jnz:jz,\ ja:jna, jna:ja, jbe:jnbe, jnbe:jbe, js:jns, jns:js, jp:jnp, jnp:jp, jpe:jpo, jpo:jpe,\ jl:jnl, jnl:jl, jge:jnge, jnge:jge, jle:jnle, jnle:jle, jg:jng, jng:jg { match j:n, pair \{ define j\#.p j define j\#.n n macro j target \\{ \\local ..next define __j ..next if ~ defined ..next\\#.switch j\#.p target else j\#.n ..next\\#.switch end if ..next: \\} \} } macro jmp target { if defined __j & __j relativeto $ & $ - __j = 0 match _,__j \{ label _\#.switch at target \} else jmp target end if } define __j ..j cmp eax,2 jbe .15 jmp .16 .15: jmp .14 .14: jmp .16 .16: .19: jz .15 sub eax,14 Code: A.ASM [43]: jmp .14 A.ASM [31] jmp [2]: match _,__j \{ label _\#.switch at target \} A.ASM [31] match [0]: match _,__j \{ label _\#.switch at target \} processed: label ..next?0.switch at .14 error: symbol already defined. _________________ smaller is better |
|||
17 Sep 2021, 13:25 |
|
Tomasz Grysztar 17 Sep 2021, 13:31
This should fix that specific issue:
Code: macro jmp target { match _,__j \{ if defined _ & _ relativeto $ & $ - _ = 0 & ~ definite _\#.switch label _\#.switch at target else jmp target end if \} } |
|||
17 Sep 2021, 13:31 |
|
CandyMan 17 Sep 2021, 16:29
An additional condition is needed to check that the first jcc instruction jumps right after the second jmp instruction, otherwise everything crashes.
Code: or al,al jnz .625 ;\ changed to JZ .624 (this possible to modify) jmp .624 ;/ .625: Code: or al,al jnz .625 ;\ changed to JZ .624 (this is bug, not possible to modify) jmp .624 ;/ lea eax,[ebp-12] .624: inc dword [eax] .625: jmp $ _________________ smaller is better |
|||
17 Sep 2021, 16:29 |
|
macomics 17 Sep 2021, 17:20
CandyMan wrote: smaller is better Code: macro jmp aim { local .a, .b, .c, .d, .e load .b word from $ - 2 load .c dword from $ - 4 load .d word from $ - 6 if ( ~ aim eqtype rax ) | (( 0xF0 and .d = 0x70 ) & ( $ + ( .b / 256 ) = .a )) | (( 0xF0FF and .d = 0x800F ) & ( $ + .c = .a )) display "Please note this place in the code and make it a little smaller.", 10 err else jmp aim end if .a: } So you will definitely be able to get rid of all such moments. But the solution is somewhat time-consuming. just as a solution, it's easier to create a macro that generates both of these instructions as needed than to write something that will remove unnecessary jmp https://flatassembler.net/docs.php?article=manual wrote: Inside macroinstruction also special operator # can be used. This operator causes two names to be concatenated into one name. It can be useful, because it's done after the arguments and local names are replaced with their values. The following macroinstruction will generate the conditional jump according to the cond argument: Code: define not.ja jna define not.jb jnb define not.jc jnc ... define not.jna ja ... ; or irps pair, ja:jna ... ; { ; match cif:nif,pair \{ ; define not.\#cif nif ; define not.\#nif cif ; \} ; } macro jif cond*, label_true*, label_false*, mispredict { local .end_label, .jmp_label if (( label_true > label_false ) & \ ( .end_label = label_false )) | \ (( label_false > label_true ) & \ ( .end_label <> label_true )) | \ ( ~ mispredict eq ) j#cond label_true .jmp_label = label_false else if label_true <> label_false not.j#cond label_false .jmp_label = label_true else label_true <> .end_label jmp label_true .jmp_label = .end_label end if if .jmp_label <> .end_label jmp .jmp_label end if .end_label: } |
|||
17 Sep 2021, 17:20 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.