Forum > General

Relocatable relative assembly jump by value instead of label - SOLVED?

<< < (2/2)

ccrause:

--- Quote from: NickleSi on May 08, 2021, 07:46:26 pm ---Compiler / linker is confused by relative short jumps with an immediate value. Thinks they are a label or something..

dec cl
jnz -15
<snip>
--- End quote ---
Any reason you want to hard code the jump distance, rather than using a label so that the linker can calculate the appropriate distance?


--- Quote from: Mr.Madguy on May 08, 2021, 09:15:57 pm ---TASM has "short" label type for this purpose, but FPC doesn't seem to support it.
<snip>
--- End quote ---
The exact syntax depends on the selected assembler mode, for Intel syntax the following code:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program project1; {$asmmode intel} begin  asm    @l1:    dec cl    jnz @l1  end;end. compiles to the following assembler (dumped from the executable using objdump on Linux 64 bit):

--- Code: ASM  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---00000000004001d0 <main>:  4001d0:       55                      push   %rbp  4001d1:       48 89 e5                mov    %rsp,%rbp  4001d4:       e8 27 61 01 00          callq  416300 <fpc_initializeunits>  4001d9:       fe c9                   dec    %cl  4001db:       75 fc                   jne    4001d9 <main+0x9>  4001dd:       e8 6e 65 01 00          callq  416750 <fpc_do_exit>  4001e2:       48 89 ec                mov    %rbp,%rsp  4001e5:       5d                      pop    %rbp  4001e6:       c3                      retq    Using AT&T syntax:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program project1; {$asmmode att} begin  asm    .L1:    dec %cl    jnz .L1  end;end.Yielding identical assembler as above.

So while the use of an immediate value is not supported by FPC, it appears that a programmer can generate the desired instructions via local labels. Or do you have a situation where the compiler + linker cannot determine the jump offset?


--- Quote from: NickleSi on May 09, 2021, 11:14:13 am ---<snip>
Yes, I use external assemblers and assembly tools, but I am an into INTEGRATED development environments...

--- End quote ---
I fully agree with this point of view.

Mr.Madguy:

--- Quote from: NickleSi on May 09, 2021, 11:14:13 am ---In my experience 'ASM syndrome' is yet another high level excuse for not doing low-level work when it's easy, as in the case I demonstrated. Easy to program whilst guaranteeing equal or better performance than the compiled version. Easy to roll-out similar methods (ie. small lines and arcs rotated 8 or 4 ways).
--
The FPC 'bitpacked' types produce pretty efficient code, but I can beat it with assembly and it's easier when it comes to nitty-gritty bit manipulation with a bit of practice. Macros reduce procedure calls... These are all tight little loops and tight, rapidly repeated procedures. Inlined code and assembler macros enable higher code engineering standards... and more speed.
--
This tiny engine could run on a 68000 or even Z80 using 16kb of tiny arc, line, circle and interpolation + a few fast math lookup tables.. It also happens to work well on modern systems.  FPC and Lazarus is a fine effort, and Delphi 7 32bit for compiled Win32 apps was a masterpiece for its time. FPC does a very good job at optimisation with plenty of control - but also lack of it at times...
--
Yes, I use external assemblers and assembly tools, but I am an into INTEGRATED development environments and assessing many.

--- End quote ---
Ok, at the end it's your choice. I can't dictate anything to you.

I'm one of those people, who also had ASM syndrome in the past. This syndrome came from simple fact, that I started my programming career on MS QBasic and wondered, how to write games, that could run on 12Mhz computer fast enough. I decided, that it was due to fact, that these games were written on ASM, so writing on ASM = faster code. I have several projects, fully written on ASM. But then I realized, that high level programming language produced equally effective code. Because at some day I said, that I would write faster code on ASM, than code produced by FPC, in one of threads on this forum, but failed, because FPC's code was faster, than mine. And on ASM I had to think too much about "I need to do everything in registers for better performance, but number of registers is limited, so I need to decide, which one to use". High level language simply does this job better.

mika:

--- Quote from: NickleSi on May 08, 2021, 07:46:26 pm ---Compiler / linker is confused by relative short jumps with an immediate value. Thinks they are a label or something..

--- End quote ---

Immediate value is deviation of label "zero". I would consider as bug fact that internal assembler and external assembler represents with label "zero" two different entities.

Treat immediate value as is does not make sense.

NickleSi:
I do not have 'asm syndrome'.. Psychobabble is the neo-way of avoiding issues I find... I do have testing the limits syndrome, before committing to a platform for personal projects... Assembly should be used sparingly for worthwhile optimisation and when it makes the job easier.. I tried to use a simple, timeless example that is still relevant for say a 'picoPi' super-microcontroller, and also other embedded / retro platforms. FPC simply cannot put two instances of a tiny macro containing a local jump in the same scope. A better example is for say a line drawing algorithm with a jump.. Here is what's inside the loop. 

add r9, rdx      // 4 or 6 ops per loop
cmp r9, rcx
db $7e; db $06   // jle @onward
  sub r9, rcx
  add rdi, rbx
// @onward:
  add rdi, rax   // st+=ht; if st>=ln then begin nib.nub+=1; st-=ln; end; nib^:=cl; nib.nub+=padW; end;

1 of 16 directions are selected, 8 of them embed the above code as a relocatable macro in the same function (yes, there are other ways, but for the sake of the example, go with it). Also if rolled out 32 times to avoid loop overhead, with an offset jump into the rolled out loop block. The above can be put in a {$i lineLoop} 'macro' and pasted 32 times in a procedure..   If I'd used a label they'd clash and produce an error, obviously... Just saying it's a bit of an ugly solution, but not a big deal...

Here's how I'd implement macros (Intel syntax+)

macro_name:[macro text]
and
macro_name:
[
  macro text
]

These macros can contain any text and are scoped so

macro_example:
[
  source: [rsi]  // renamed registers, here local to macro_example but could be global in an asm block in the interface section
  target: [rdi]
  count:  [rcx]
// ... 
  mov rax, [source]
  mov [target], rax
// ... 
]

In use 'macro_example' embeds the text inline, but 'call macro_example' can also be used.. Remember, FPC won't inline assembly functions, it's macros don't work in assembly, only {$i filename} linking to an external file works.. Messy when you want to make a code 'lego set' for simple ops.

I do not have 'asm syndrome'.. Psychobabble is the neo-way of avoiding issues I find... I do have testing the limits syndrome, before committing to a platform for personal projects... Assembly should be used sparingly for worthwhile optimisation and when it makes the job easier.. I tried to use a simple, timeless example that is still relevant for say a 'picoPi' super-microcontroller, and also other embedded / retro platforms. FPC simply cannot put two instances of a tiny macro containing a local jump in the same scope. A better example is for say a line drawing algorithm with a jump.. Here is what's inside the loop. 

add r9, rdx      // 4 or 6 ops per loop
cmp r9, rcx
db $7e; db $06   // jle @onward
  dec r9
  add rdi, rbx
// @onward:
  add rdi, rax   // st+=h; if st>=l then begin nb+=1; st-=l; end; nb^:=cl; nb+=padW; end;

1 of 16 directions are selected, 8 of them embed the above code as a relocatable macro in the same function (yes, there are other ways, but for the sake of the example, go with it). Also if rolled out 32 times to avoid loop overhead, with an offset jump into the rolled out loop block. The above can be put in a {$i lineLoop} 'macro' and pasted 32 times in a procedure..   If I'd used a label they'd clash and produce an error, obviously... Just saying it's a bit of an ugly solution, but not a big deal...

Here's how I'd implement macros (Intel syntax+)

macro_name:[macro text]
and
macro_name:
[
  macro text
]

These macros can contain any text and are scoped so

macro_example:
[
  source: [rsi]  // renamed registers, here local to macro_example but could be global in an asm block in the interface section
  target: [rdi]
  count:  [rcx]
// ... 
  mov rax, [source]
  mov [target], rax
// ... 
]

In use 'macro_example' embeds the text inline, but 'call macro_example' can also be used.. Remember, FPC won't inline assembly functions, it's macros don't work in assembly, only {$i filename} linking to an external file works.. Messy when you want to make a code 'lego set' for simple ops.

Cross-platform human-machine languages can be also be implemented with macros...

ie... 'move', 'put' and/or 'get'  replacing mov, 'op' or 'do' replacing 'call', 'to' or 'go' for jump, and working on ARM, X86, ++ with appropriate embedded compiler directive IFDEFs... Many possibilities. Good for engine building.

Navigation

[0] Message Index

[*] Previous page

Go to full version