flat assembler
Message board for the users of flat assembler.
![]() Goto page 1, 2, 3, 4, 5 Next |
Author |
|
aaro 14 Mar 2004, 11:50
Code: F6 /0 ib TEST r/m8,imm8 AND imm8 with r/m8; set SF, ZF, PF according to result F6 works only for 8 bit registers and memory |
|||
![]() |
|
S.T.A.S. 14 Mar 2004, 15:34
aaro wrote:
What is the difference between 8 bit operand and 32 bit one, where most significant 24 bits are zeros? With TEST result is not saved back to memory, just flags are actual: Code: byte 0 byte 1 byte 2 byte 3 01234567 01234567 01234567 01234567 XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX -- memory operand (1st) 01100000 00000000 00000000 00000000 -- 32 bit mask (2nd - immediate operand) 0XX00000 00000000 00000000 00000000 -- temporary result XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX -- memory operand (1st) 01100000 "virtual zeros" -- 8 bit mask (2nd - immediate operand) 0XX00000 -- temporary result Z flag depends on bits marked X in result - so it's equal in both cases P flag depends on the least significant byte - bits 0..7 are equal in both cases S flag is ALWAYS clear when we use 2nd operand < 80000000h with 32 bit operands, so it would be clear if.. The ONLY incompatibility I see - when 7th bits of 1st & 2nd opersnds are set. In this case, with 8 bit operangs we'll get SF=1, but with 32 bit operand SF=0. So the question is: who would do such thing: Code: test dword [foo], 80h js foo_proc This code seems rather strange to me. If my logic is right, no one will write such incompatible stuff.. |
|||
![]() |
|
JohnFound 14 Mar 2004, 16:31
In other words, you want to force the programmer that write:
"test eax, imm8" to actually write "test al, imm8". Why not in this case to substitute "add eax, 1" with "inc eax" and "mov eax, 0" with "xor eax, eax" -> they are smaller in size too. IMHO, it is not very good. At least you can get mentioned opcode, simply using 8bit register instead of 32bit register - it is programmer choice, not assembler choise. Regards |
|||
![]() |
|
aaro 14 Mar 2004, 18:28
I agree with JohnFound here, but in case someone wants that kind of behavior here's macro for that:
Code: macro test arg1, arg2 { if arg2 eqtype 1 if arg2 < 80h test byte arg1, arg2 else test arg1, arg2 end if else test arg1, arg2 end if } Works only with memory |
|||
![]() |
|
S.T.A.S. 15 Mar 2004, 01:36
JohnFound wrote: In other words, you want to force the programmer that write: Hm.. I don't see test eax, imm8 inctruction in my reference. Though and mreg16/32, imm8 (sign extended) is available, of cource. Quote: Why not in this case to substitute "add eax, 1" with "inc eax" and "mov eax, 0" with "xor eax, eax" -> they are smaller in size too. Yes, I see your point and fully agree here. These instruction are NOT equivalent - they affects flags by different ways. aaro wrote: here's macro for that .. Also, I'd like to give you the real example from Fresh project (just a result of quick searh) file Controls.asm -> ;-- WM_WINDOWPOSCHANGED Code: test eax, SWP_NOSIZE ;; SWP_NOSIZE = 0001h My point is: with TEST instruction, there's NO matter what is actual size of operang. Since there NO 8 or 32 bit result at all. Only some FLAGS, and how many of these flags are actually used? We can calculate the results for affected flags in both variants of TEST instruction using bitwise logic. And see when they are equal or not. Some cases with SF are the weak side of my theory, but restricting size of 2nd operand to 7bit could be workaround to FULL compatibility. PS Sorry, my English isn't good, may be I just can't give good explanation of my idea? |
|||
![]() |
|
vid 15 Mar 2004, 05:46
I agree with S.T.A.S.
by the way, same optimization is done with cmp instruction (cmp rm32,imm8) and nobody had problems with it, as it is functionally equivalent. If you need to rely on size of instruction, you can force operand size with size operator. |
|||
![]() |
|
comrade 15 Mar 2004, 07:57
I agree with JohnFound rather. Programmer would know that "xor eax,eax" is shorter than "mov eax,0", and that is something he/she learns. Similarly he/she would learn to use "test al, mask" as opposed to "test eax, mask".
The assembler should do what the programmer asks from it, and if programmer asks for "test eax,mask", so be it with the longer opcode. |
|||
![]() |
|
JohnFound 15 Mar 2004, 08:23
Well, that example from Fresh, almost convinced me.
![]() Maybe such optimization will be appropriate for imm8 below $80 to avoid problems with Sign flag. Actually I whould like to read Privalov's opinion on this subject too. You may be sure that I am fully agree with him on such subjects. ![]() Regards. |
|||
![]() |
|
S.T.A.S. 15 Mar 2004, 08:33
vid wrote: same optimization is done with cmp instruction (cmp rm32,imm8) To be absolutely correct there is the difference - cmp & other sign extended instructions are documented ones. But this case with test is NOT. Intels docs tell us, that there is difference between 8bit & 32bit variants.. Of cource, this is right, if we need to STORE the result of operation.. This is like some kind of trick - based on bitwise logic. It works, but it isn't officially recommended for use.. At the other side there's another example of other 2 "different" instructions Code: 83E0 08 and eax, 8 25 08000000 and eax, 8 Though it's well docummented in manuals |
|||
![]() |
|
Tomasz Grysztar 15 Mar 2004, 08:55
I agree that in case of immediate values in range 0-7Fh these two TEST instructions are exactly equivalent, so I could make such optimization - however it would confuse some people when they get disassembly a bit different from the source... In the case of immediate values in range 80h-0FFh I cannot agree at all.
|
|||
![]() |
|
aaro 15 Mar 2004, 09:31
Quote:
Because of the sign flag. Here's new version that works with registers too: Code: macro test arg1, arg2 { if arg2 eqtype 1 if arg2 < 80h if arg1 eq eax test al, arg2 else if arg1 eq ebx test bl, arg2 else if arg1 eq ecx test cl, arg2 else if arg1 eq edx test dl, arg2 else test byte arg1, arg2 end if else test arg1, arg2 end if else test arg1, arg2 end if } |
|||
![]() |
|
S.T.A.S. 15 Mar 2004, 10:40
aaro wrote: new version that works with registers Otherwise "test EPB, 70h" will fail.. Anyway it would be a solution Privalov wrote: it would confuse some people when they get disassembly a bit different from the source.. I suppose it is always a good idea ![]() Of cource, S flag is restricting to 7bit operands, if it will be done at compiler level. It is also logical, bacouse other short instruction do use 00..7Fh positive numbers, other are interpreted as negative. |
|||
![]() |
|
aaro 15 Mar 2004, 10:50
Code: macro test arg1, arg2 { if arg2 eqtype 1 if arg2 < 80h if arg1 eq eax test al, arg2 else if arg1 eq ebx test bl, arg2 else if arg1 eq ecx test cl, arg2 else if arg1 eq edx test dl, arg2 else if arg1 eqtype eax test arg1, arg2 else test byte arg1, arg2 end if else test arg1, arg2 end if else test arg1, arg2 end if } |
|||
![]() |
|
Tomasz Grysztar 15 Mar 2004, 13:26
S.T.A.S. wrote: Woudn't it enforce them to study some more things about math and boolean algebra? It's not always so good when you're receiving tons of "bug reports" from people that haven't yet studied it enough. ![]() Anyway I am convinced - this is a good feature. |
|||
![]() |
|
Tomasz Grysztar 20 Mar 2004, 13:22
Hmm, and what about LEA->MOV substitution? Both don't affect any flags, so the same reasoning could be applied to this case. Only it would be harder to allow programmer to force the LEA instruction when he really wants it (with optimized TEST I have made for fasm 1.52 you can always write TEST EAX,DWORD 1 to avoid optimization).
|
|||
![]() |
|
Dryobates 20 Mar 2004, 19:36
I think that you should only inform programmer that something could be change in order to make better code. Just write the line where it is and how it can be changed. It would be nice to still leave decision for programmer. You don't want make macro assembler (TASM, MASM, HLA etc.), do you?
|
|||
![]() |
|
S.T.A.S. 23 Mar 2004, 11:02
Privalov wrote: what about LEA->MOV substitution? Do you mean this case? (as to me, I simply do not know where LEA can be used in such context) Code: 8D05 21436587 lea eax, dword [ds:87654321] B8 21436587 mov eax, 87654321 |
|||
![]() |
|
Tomasz Grysztar 23 Mar 2004, 11:34
And what about converting "test eax,100h" to "test ah,1"?
And if we decide to do it, what about "test dword [0],100h" to "test byte [1],1"? |
|||
![]() |
|
Frank 23 Mar 2004, 12:45
Why not "pushf / xor eax,eax / popf" as an automatic replacement for "mov eax, 0"? Plus more special-case syntax for those who don't want the feature?
It is such a pity -- FASM used to be a logical, straightforward, consistent, predictable, easy-to-use assembler, and now everyone wants to turn it into a compiler. |
|||
![]() |
|
Goto page 1, 2, 3, 4, 5 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.