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 |
|
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. |
|||
12 Dec 2005, 15:49 |
|
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.
|
|||
12 Dec 2005, 15:52 |
|
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. |
|||
15 Dec 2005, 00:01 |
|
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 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] 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 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. |
|||
15 Dec 2005, 02:20 |
|
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:
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. |
|||
15 Dec 2005, 02:39 |
|
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 |
|||
15 Dec 2005, 07:30 |
|
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. |
|||
15 Dec 2005, 10:12 |
|
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 } 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. |
|||
15 Dec 2005, 13:08 |
|
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?
|
|||
15 Dec 2005, 13:34 |
|
LocoDelAssembly 15 Dec 2005, 18:08
My contribution
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 } 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 |
|||
15 Dec 2005, 18:08 |
|
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 |
|||
15 Dec 2005, 18:19 |
|
LocoDelAssembly 15 Dec 2005, 18:27
Thanks Tomasz
Do you have another idea of how to short macro "__re" even more? |
|||
15 Dec 2005, 18:27 |
|
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). |
|||
15 Dec 2005, 18:29 |
|
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 |
|||
15 Dec 2005, 18:54 |
|
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.
|
|||
15 Dec 2005, 18:55 |
|
Tomasz Grysztar 15 Dec 2005, 19:06
Do you have some nice proposal of directive that would turn on the "smart" optimizations?
|
|||
15 Dec 2005, 19:06 |
|
rugxulo 15 Dec 2005, 19:27
Seriously? No, but in jest ...
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) |
|||
15 Dec 2005, 19:27 |
|
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 |
|||
15 Dec 2005, 19:34 |
|
Tomasz Grysztar 15 Dec 2005, 19:42
Right, corrected it.
|
|||
15 Dec 2005, 19:42 |
|
Goto page Previous 1, 2, 3, 4, 5 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.