flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > "short" TEST instruction

Goto page Previous  1, 2, 3, 4, 5  Next
Author
Thread Post new topic Reply to topic
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 12 Dec 2005, 15:13
locodelassembly wrote:
I don't understand what are you saying about "cmp eax, byte My_Value"
it can be encoded in two ways, with sign-extended byte or with full dword (or word in 16 bits)

--------------------

Quote:
the first and obvious is fasm doesn't support the size operator "byte"
it does

--------------------

What i want is, that when someone reads my code, he sees:
Code:
cmp eax, byte Some_Initial_Value
Value_To_Compare label byte at $-1    
To which current equivalent (due to future-bug-proofness and readability) is:
Code:
cmp eax, Some_Initial_Value  ;should generate cmp eax,imm8
Value_To_Compare label byte at $-1
if Some_Initial_Value < -128 | Some_Initial_Value > 127
  display 'some error'
end if    
which is uglier, unclear, still harder to read etc. etc.

--------------------

Quote:
My proposal is:
retn = C3
retn 0 = C3
retn word 0 = C2 0000
"retn 0" itself says there has to be "0" somewhere in code, optimization is only for cases when nothing hints you which option to choose, so compiler is free to chose any option.
Post 12 Dec 2005, 15:13
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 12 Dec 2005, 15:49
About size operator "byte" sorry you are right, "byte" is not supported when you write something like "[eax+byte 0]" and I thought it can't be used anywhere. However note when you write "cmp eax, byte 0" FASM says "Error: operand sizes do not match".

If "retn 0" itself says there is has to be a "0" somewhere in code, why "lea eax, [eax+0]" doesn't say the same? I don't undestand why the decision of optimize an imm deleting it is only applied to addressing and for imm operands not.
Post 12 Dec 2005, 15:49
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 12 Dec 2005, 15:52
vid: it was working this way for some instructions in the early versions of fasm (with the "imul" instruction actually for a long time, since at first I forgot to update it with the others - you can check out that 1.56 still accepted "imul eax,byte 0"), but I changed it for the current one for the reasons I explained in the other thread.
Post 12 Dec 2005, 15:52
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 15 Dec 2005, 00:01
tomasz: i believe you mean this one

I still disagree with your arguments, if you are going to do some more low-level things, you can end up with code like one you see upwards.

And I think I don't get the design principes then. What I find as a most straightforward syntax is this:
<mnemonics> <args>

- if args doesn't have size specified use best one (but still keep the mnemonics, eg. don't change MOV to LEA, altough they can be functionally equivalent)

- if some of arguments has specified size, then try to encode using instruction with specified argument size, and if such does not exist, then throw error.

You say that after deep thinking you found this design bad, what's wrong with it then? If there is instruction which compares 16bit register with 8byte constant, then i await this "cmp r16, byte imm8" will generate it.

This is IMO more "clear" than tricking assembler to do what i want. That's why i like FASM most, you don't have to trick it to get result you want, like you had to with TASM.

Please rethink it and let me know what's wrong with this.
Post 15 Dec 2005, 00:01
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20355
Location: In your JS exploiting you and your system
revolution 15 Dec 2005, 02:20
Quote:
but still keep the mnemonics, eg. don't change MOV to LEA, altough they can be functionally equivalent
Personally I see nothing wrong with encoding "lea eax,[ebx]" as "mov eax,ebx". What is the problem with it? Why don't you like it?

When using equates and/or structures sometimes a constant value can be zero and it is difficult to recognise this when coding an instruction like this:
Code:
lea eax,[ebx+STRUCTURE.member]    
How can we know if the constant is zero? Answer: we cannot be sure, especially if the structure definition is in a different file or written by a different person. We are best to let the assembler decide the best encoding at assembly time.

I can see no advantage to leaving the LEA in the target file. It just uses up extra space in the file. The MOV is a better alternative. I can't think of any instance where I deliberately want to have something like "lea eax,[ebx]", perhaps someone can please explain why they prefer this inefficient coding. If your reason is using a debugger then you will be dissappointed to discover that OLLY will happily display all of the following as the same:
Code:
db 08dh,040h,000h
db 08dh,044h,020h,000h
db 03eh,08dh,044h,020h,000h
db 08dh,080h,000h,000h,000h,000h
db 08dh,004h,005h,000h,000h,000h,000h
db 03eh,08dh,004h,005h,000h,000h,000h,000h    
All display as "LEA EAX,[EAX]", so even disassemblers will not distinguish all the instructions properly.

The same goes for all optimisations where functionality is the same, TEST, LEA, OR, AND, XOR. I much prefer the assembler to make good compact code than have it bloat the target with unnecessary bytes using up precious space in the caches.
Post 15 Dec 2005, 02:20
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 15 Dec 2005, 02:39
revolution wrote:
Personally I see nothing wrong with encoding "lea eax,[ebx]" as "mov eax,ebx". What is the problem with it? Why don't you like it?

Sometimes you need to be sure some proper opcode is generated, this can easily fool you. I think result should be easily predictable.

Quote:

When using equates and/or structures sometimes a constant value can be zero and it is difficult to recognise this when coding an instruction like this:
Code:
lea eax,[ebx+STRUCTURE.member]    
How can we know if the constant is zero? Answer: we cannot be sure, especially if the structure definition is in a different file or written by a different person. We are best to let the assembler decide the best encoding at assembly time.

You got the point here, but problem is that it isn't What-you-get-is-what-you-wrote, which IMO isn't good approach. For me, good tool is one where i don't have to look "how did it really do it", it should be always obvious from code. It should "choose" only where my code leaves space for it. Result should always stay my code, not my code optimized.

Like when you write "xor eax, constant", you specify it should be XOR instruction, it should have destination eax, but nothing about size of constant. So compiler can choose any form of XOR (not other mnemonics)which xors EAX with this constant. It's on compiler to choose from such possiblities, and you get what you wrote.

With your approach we would end up with ignoring instructions like "xor eax,0", or at least replacing them with nops.
Post 15 Dec 2005, 02:39
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20355
Location: In your JS exploiting you and your system
revolution 15 Dec 2005, 07:30
Quote:
With your approach we would end up with ignoring instructions like "xor eax,0", or at least replacing them with nops
Actually we can't replace with nops because the flags are not updated correctly. We have to be sure that it always functionally equivalent. I only propose replacing with shorter code if all aspects are the same. For XOR we can use "XOR eax,byte 0" and "XOR eax,dword 0" but nothing else. And the assembler will already automatically optimise "XOR eax,0", surely you don't have aproblem with that kind of optimisation, so we can also allow LEA eax,[ebx] to become MOV eax,ebx. There is no difference in function, the only difference is just the way the disassembler likes to display the resulting code for your viewing.
Post 15 Dec 2005, 07:30
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 15 Dec 2005, 10:12
vid wrote:
You say that after deep thinking you found this design bad, what's wrong with it then? If there is instruction which compares 16bit register with 8byte constant, then i await this "cmp r16, byte imm8" will generate it.

First: there is no instruction which compares 16-bit register with 8-bit constant, how could it? There is a variant of 16-bit instruction encoding, which stores only 8 bits of contant that are then are sign-extended to the 16 bits for operation. When you write "cmp ax,-1" it uses the shorter variant but certainly "-1" is 16-bit constant here.

Quote:
Please rethink it and let me know what's wrong with this.

I already gave an example. Assuming we've got "var dw ?" definition, this:
Code:
cmp [var],al    

would give an error, but this:
Code:
cmp [var],byte 0    

would not. It was one of the main reasons why this new solution got designed.

Or maybe use "cmpsx" mnemonic for the sign-extending form? Idea a bit similar to using "ld ax,bx" and "st bx,ax" to choose one of the two different forms of "mov ax,bx". Going into the reverse direction than optimizing generally discussed in this thread. I personally would go for the "test" optimization, and "lea" to "mov" one, but I decided I can live without them when they are so strongly opposed. However the flexibility that was one of fasm's principles, means only that you should be able to exactly specify which one of the functionally different variants of instructions you want to use - what I needed for OS development (like making direct 32-bit far jump in 16-bit mode or vice versa), while I still believe the assembler should give you the total abstraction from the instruction encodings.
Post 15 Dec 2005, 10:12
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20355
Location: In your JS exploiting you and your system
revolution 15 Dec 2005, 13:08
Hehe, just for fun I wrote this:
Code:
macro lea [stuff] {
   common
   local b1,b2,b3
   virtual
      b1=0
      b2=0
      lea stuff
      if ($-$$)=2
         load b1 byte from $$
         load b2 byte from $$+1
      else if ($-$$)=3
         load b1 byte from $$
         load b2 byte from $$+1
         load b3 byte from $$+2
         if (b1=8dh & b2=24h & b3=24h) | \ ;lea esp,[esp]
            (b1=8dh & b2=6dh & b3=00h)     ;lea ebp,[ebp]
            b2=0
         else if ~(b1=8dh & b2=2ch & b3=24h) & \ ;lea ebp,[esp]
                 ~(b1=8dh & b2=65h & b3=00h)     ;lea esp,[ebp]
            b1=0
         end if
      end if
   end virtual
   b3=(b2 and 111000b) shr 3
   if b1=08dh
      if ~(((b2 and 111b)=b3)&(b3<>4))
         db 08bh,b2 or 0c0h
      else
         ;do nothing
      end if
   else
      lea stuff
   end if
}    
LEA EAX,[EBX] becomes MOV EAX,EBX.

And as a bonus it optimises LEA to such an extent that "LEA EAX,[EAX]" and similar NOP's are completely ignored and use no space in the code.
Post 15 Dec 2005, 13:08
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 15 Dec 2005, 13:34
Nice - writing optimizing macro I also proposed for the TEST several posts above. So are we going to make some package of code optimizing macros?
Post 15 Dec 2005, 13:34
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 15 Dec 2005, 18:08
My contribution Very Happy

Code:
macro __re type*, expr
{ 
  if expr eq
    re # type 
  else if expr = 0 
    if 1
    match =word _expr, expr 
    \{ 
      re # type _expr 
      else 
    \} 
      re # type 
    end if
  else
    re # type expr 
  end if 
} 

macro ret expr 
{ 
  __re t, expr 
} 

macro retn expr 
{ 
  __re tn, expr 
} 

macro retf expr 
{ 
  __re tf, expr 
}    
In the case you don't want the optimization writing "ret word expr" is enough. expr is any expression and if is "0" or the result of the expression is 0 then putting "word" before the expression the optimization will not be applied.

I dislike a little the use of the "ok" variable to know if "expr" matched with "word", is there another way to implement that kind of "elseMatch"?

[edit]I applied Tomasz's suggestion[/edit]


Last edited by LocoDelAssembly on 15 Dec 2005, 18:25; edited 1 time in total
Post 15 Dec 2005, 18:08
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 15 Dec 2005, 18:19
Another way? Maybe something like:
Code:
    if 1
    match =word _expr, expr
    \{
      re # type _expr
      else
    \}
      re # type
    end if    
Post 15 Dec 2005, 18:19
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 15 Dec 2005, 18:27
Thanks Tomasz

Do you have another idea of how to short macro "__re" even more?
Post 15 Dec 2005, 18:27
View user's profile Send private message Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 15 Dec 2005, 18:29
Other assemblers (A86/A386, NBASM32, PASS32) do such optimizations by default or via commandline options/directives in the source code. If FASM is not designed in favor of complicated cmdline opts, then directives are the way to go (e.g., NBASM32: .OPTON and .OPTOFF, or PASS32: .SMART).

Privalov, you once mentioned making ret assemble into the appropriate retn or retf but didn't implement it because of opposition. I still think this can be a good idea (if it can be disabled, of course).
Post 15 Dec 2005, 18:29
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 15 Dec 2005, 18:54
Here's my try for the TEST:
Code:
macro test op,val
{
  addr@test equ
  match size [addr], op \{ addr@test equ addr \}
  match size =ptr addr, op \{ addr@test equ addr \}
  if val eqtype 0
    virtual at 0
      test op,val
      repeat $
        load opcode@test byte from %-1
        if opcode@test <> 66h & opcode@test <> 67h
          break
        end if
      end repeat
    end virtual
    if opcode@test = 0F7h & ~ addr@test eq
      if val = val and 7Fh
        test byte [addr@test],val
      else if val = val and 7F00h
        test byte [addr@test+1],val shr 8
      else if val = val and 7F0000h
        test byte [addr@test+2],val shr 16
      else if val = val and 0FF000000h
        test byte [addr@test+3],val shr 24
      else if val = val and 0FFFF0000h
        test word [addr@test+2],val shr 16
      else
        test op,val
      end if
    else if op eq eax & val = val and 7Fh
      test al,val
    else if op eq eax & val = val and 7F00h
      test ah,val shr 8
    else if op eq ebx & val = val and 7Fh
      test bl,val
    else if op eq ebx & val = val and 7F00h
      test bh,val shr 8
    else if op eq ecx & val = val and 7Fh
      test cl,val
    else if op eq ecx & val = val and 7F00h
      test ch,val shr 8
    else if op eq edx & val = val and 7Fh
      test dl,val
    else if op eq edx & val = val and 7F00h
      test dh,val shr 8
    else if op eq ax & val = val and 7Fh
      test al,val
    else if op eq ax & val = val and 0FF00h
      test ah,val shr 8
    else if op eq bx & val = val and 7Fh
      test bl,val
    else if op eq bx & val = val and 0FF00h
      test bh,val shr 8
    else if op eq cx & val = val and 7Fh
      test cl,val
    else if op eq cx & val = val and 0FF00h
      test ch,val shr 8
    else if op eq dx & val = val and 7Fh
      test dl,val
    else if op eq dx & val = val and 0FF00h
      test dh,val shr 8
    else
      test op,val
    end if
  else
    test op,val
  end if
}    


Last edited by Tomasz Grysztar on 15 Dec 2005, 19:41; edited 1 time in total
Post 15 Dec 2005, 18:54
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 15 Dec 2005, 18:55
rugxulo: The "ret" in the "proc" context (as this is the only case when you can choose the "retn" or "retf" form automatically) is also implemented as macros for fasm. I haven't yet made publically available "proc" macro packages for segmented modes, though.
Post 15 Dec 2005, 18:55
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 15 Dec 2005, 19:06
Do you have some nice proposal of directive that would turn on the "smart" optimizations?
Post 15 Dec 2005, 19:06
View user's profile Send private message Visit poster's website Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2341
Location: Usono (aka, USA)
rugxulo 15 Dec 2005, 19:27
Seriously? No, but in jest ... Smile

1). TWEAKED (?)
2). HAXOR (silly)
3). NOBLOAT or BLOATOFF (too weird?)
4). GENIUS (since you have to be to understand all this, which I don't) Razz
Post 15 Dec 2005, 19:27
View user's profile Send private message Visit poster's website Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 15 Dec 2005, 19:34
Code:
    else if op eq ebx & val = val and 7Fh 
      test al,val 
    else if op eq ebx & val = val and 7F00h 
      test ah,val shr 8 
    


That's wrong.
[edit]This too
Code:
    else if op eq bx & val = val and 7Fh 
      test al,val 
    else if op eq bx & val = val and 0FF00h 
      test ah,val shr 8 
    
[/edit]
Post 15 Dec 2005, 19:34
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 15 Dec 2005, 19:42
Right, corrected it.
Post 15 Dec 2005, 19:42
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 Previous  1, 2, 3, 4, 5  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


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.