The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: jj2007 on May 07, 2009, 02:14:47 PM

Title: Olly and test
Post by: jj2007 on May 07, 2009, 02:14:47 PM
include \masm32\include\masm32rt.inc

.code

start:
  test ecx, eax   ; ecx in front
  test ecx, ebx
  test ecx, edx
  test ecx, edi
  test ecx, esi
  test ecx, ebp
  nop
  test eax, ecx   ; ecx behind
  test ebx, ecx
  test edx, ecx
  test edi, ecx
  test esi, ecx
  test ebp, ecx
  nop
  print "OK"
  getkey
  exit

end start


Note the order in Olly, 23.12.2008:

CPU Disasm
Address   Hex dump                   Command                      Comments
<ModuleEn Ú. 85C8                    test eax, ecx
00401002  ³? 85CB                    test ebx, ecx
00401004  ³? 85CA                    test edx, ecx
00401006  ³? 85CF                    test edi, ecx
00401008  ³? 85CE                    test esi, ecx
0040100A  ³? 85CD                    test ebp, ecx
0040100C  ³? 90                      nop
0040100D  ³. 85C1                    test ecx, eax
0040100F  ³? 85D9                    test ecx, ebx
00401011  ³? 85D1                    test ecx, edx
00401013  ³? 85F9                    test ecx, edi
00401015  ³? 85F1                    test ecx, esi
00401017  ³? 85E9                    test ecx, ebp
00401019  ³? 90                      nop


By design? ::)
Title: Re: Olly and test
Post by: mitchi on May 07, 2009, 02:22:17 PM
Nice discovery !!!  :green
I use Olly a lot and I never noticed.
Title: Re: Olly and test
Post by: dedndave on May 07, 2009, 06:21:49 PM
ouch!
of course, it's not olly - it's masm
they must be trying to optimize somehow
maybe there's a switch or directive to turn optimization off
i think if you used registers that were different (other than ecx - ecx - ecx...)
the assembler would not be able to figure out the optimization

that really stinks - it takes some flexibility away from the programmer

another way to work around it would be to use "db" to specify the opcodes
hopefully, the assembler at least places THOSE in order - lol

if you put jz after each test ?
can't alter it then, either
Title: Re: Olly and test
Post by: Vortex on May 07, 2009, 06:28:37 PM
Hi jj2007,

Which is the version of your Ollydbg copy?
Title: Re: Olly and test
Post by: jj2007 on May 07, 2009, 06:36:49 PM
Quote from: Vortex on May 07, 2009, 06:28:37 PM
Hi jj2007,

Which is the version of your Ollydbg copy?

Olly 2.0 beta 2 of 23.12.2008

As to optimisation: The order is always reversed ... doesn't sound plausible ::)
Title: Re: Olly and test
Post by: dedndave on May 07, 2009, 06:40:50 PM
huh ?  :dazzled:

that makes no sense

my code goes one direction and EIP goes the other ? - lol
now, i am REALLY new to asm
Title: Re: Olly and test
Post by: Jimg on May 07, 2009, 07:03:51 PM
I think it's olly.  It's the same in version 1.1

if you look at
and ecx,eax
it encode the same as test ecx,eax with C8
Title: Re: Olly and test
Post by: dedndave on May 07, 2009, 07:35:47 PM
ahhhhhhhhhhhhhh
lol
i thought it was changing the order of instructions   ::)

new forum ID for me.......... Im2stoopid

just because you can afford a Mercedes, doesn't mean you can drive it
(having a high IQ <> using it)

might be a translation table in olly
use olly to fix olly  :bg

i wonder if it does the same thing for XCHG
Title: Re: Olly and test
Post by: jj2007 on May 07, 2009, 07:46:09 PM
Quote from: Jimg on May 07, 2009, 07:03:51 PM
I think it's olly.  It's the same in version 1.1

if you look at
and ecx,eax
it encode the same as test ecx,eax with C8

Yeah, it's pretty obvious... :bg

  test ecx, eax   ; ecx in front
  and ecx, eax   ; ecx in front
  test ecx, ebx
  and ecx, ebx
  test ecx, edx
  and ecx, edx
  nop
  test eax, ecx   ; ecx behind
  and eax, ecx   ; ecx behind
  test ebx, ecx
  and ebx, ecx


85C8                         test eax, ecx
23C8                         and ecx, eax
85CB                         test ebx, ecx
23CB                         and ecx, ebx
85CA                         test edx, ecx
23CA                         and ecx, edx
90                           nop
85C1                         test ecx, eax
23C1                         and eax, ecx
85D9                         test ecx, ebx
23D9                         and ebx, ecx
Title: Re: Olly and test
Post by: Jimg on May 07, 2009, 08:12:18 PM
Looks fine in debug
1401:056C 90            NOP
1401:056D 85C8          TEST    CX,AX
1401:056F 23C8          AND     CX,AX
1401:0571 85CB          TEST    CX,BX
1401:0573 23CB          AND     CX,BX
1401:0575 85CA          TEST    CX,DX
1401:0577 23CA          AND     CX,DX
1401:0579 90            NOP
1401:057A 85C1          TEST    AX,CX
1401:057C 23C1          AND     AX,CX
1401:057E 85D9          TEST    BX,CX
1401:0580 23D9          AND     BX,CX
1401:0582 90            NOP
Title: Re: Olly and test
Post by: jj2007 on May 07, 2009, 08:16:29 PM
Now the really tough question: Does it matter?
As far as I can see, test eax, ebx sets the same flags as test ebx, eax
Title: Re: Olly and test
Post by: dedndave on May 07, 2009, 08:22:15 PM
no diff
xchg ?
Title: Re: Olly and test
Post by: Jimg on May 07, 2009, 09:17:22 PM
I assume you are asking for timing purposes, because it certainly doesn't matter functionally.   So time it and find out :P
Title: Re: Olly and test
Post by: dedndave on May 07, 2009, 10:05:01 PM
no - i was curiouis if olly swapped registers - it would tell you if the instructions use the same table
of course, XCHG EAX,reg is special, and generates a single byte - XCHG reg,EAX is a 2 byte op-code
i was curious to see what olly did - assemblers should optimize by replacing XCHG reg,EAX with the XCHG EAX,reg form
Title: Re: Olly and test
Post by: PauloH on May 08, 2009, 01:12:50 AM
Hi,

I compiled this with goasm:


#DEFINE WIN32_LEAN_AND_MEAN
#DEFINE LINKFILES
#include <windows.h>

.code

start:
  test ecx, eax   ; ecx in front
  test ecx, ebx
  test ecx, edx
  test ecx, edi
  test ecx, esi
  test ecx, ebp
  nop
  test eax, ecx   ; ecx behind
  test ebx, ecx
  test edx, ecx
  test edi, ecx
  test esi, ecx
  test ebp, ecx
  nop
invoke ExitProcess, 0


Then, ollydbg 2.0 and 1.10 show it:

<ModuleEntryPoint>:                         

        TEST ECX,EAX
        TEST ECX,EBX
        TEST ECX,EDX
        TEST ECX,EDI
        TEST ECX,ESI
        TEST ECX,EBP
        NOP
        TEST EAX,ECX
        TEST EBX,ECX
        TEST EDX,ECX
        TEST EDI,ECX
        TEST ESI,ECX
        TEST EBP,ECX
        NOP
        PUSH 0
        CALL ExitProcess                     


Why?  :bg
Title: Re: Olly and test
Post by: Vortex on May 08, 2009, 04:38:31 PM
Hi Paulo,

The output matches the source code, no?
Title: Re: Olly and test
Post by: dedndave on May 08, 2009, 06:27:31 PM
Vortex -
Functionally, it does - Olly seems to swap the destination and source registers in the text listing
Odd that it does this on instructions where it does not matter, but gets them right when it does matter
Title: Re: Olly and test
Post by: BlackVortex on May 08, 2009, 11:09:05 PM
Quote from: dedndave on May 08, 2009, 06:27:31 PM
Vortex -
Functionally, it does - Olly seems to swap the destination and source registers in the text listing
Odd that it does this on instructions where it does not matter, but gets them right when it does matter

Are you sure it's Olly ?  I'm not on my development machine so I can't assemble the test case, but try with another disassembler, I suggest Hdasm (freeware) or Hiew (limited trial)

I'm surprised you haven't tried another disassembler already !
Title: Re: Olly and test
Post by: dedndave on May 08, 2009, 11:34:11 PM
well, JJ checked the op-codes against references
so - must be Olly
it was confirmed by others, as well
Title: Re: Olly and test
Post by: jj2007 on May 08, 2009, 11:39:36 PM
Quote from: dedndave on May 08, 2009, 11:34:11 PM
well, JJ checked the op-codes against references
so - must be Olly
it was confirmed by others, as well


I am not so sure - see Paulo's post at the end of page 1. He tried goasm and found the same order in Olly. So there are two possibilities:
1. goasm and olly have the same bug
2. masm is buggy

Based on my long-standing experience with Microsoft (TM) products, I tend to favour option 2 :toothy
Title: Re: Olly and test
Post by: dedndave on May 09, 2009, 12:57:01 AM
Normally, I might agree with you JJ.
But MASM gets those codes from a table.
they get certain bits of the second byte for the destination register and certain bits for the source register and OR them together
They use the same tables for some of the other instructions where it would make the code not work.

I am guessing here - the GoAsm guys used Olly as an opcode reference ?

I went back to the old 16 bit op-codes
they will be AX and CX instead of EAX and ECX, of course
but, this way, both MASM and Olly are eliminated from the equation

85C1  TEST CX,AX
85C8  TEST AX,CX

using good old 16-bit MS (XP version) debug that we all know and trust, it is backwards, also - lol
here is how you can tell for sure
instead of using the TEST instruction, use XCHG (i have been trying to get someone to try it - no luck - i do not have Olly installed)
the reason is, XCHG AX,CX is a special one-byte form (or XCHG EAX,ECX)
XCHG CX,AX is a two-byte form (or XCHG ECX,EAX)
you will know for sure right away if the source/destination registers are swapped, by the length of the op-code

using MS (xp ver) debug i did this....
91    XCHG CX,AX (we know this is reversed because XCHG CX,AX is two bytes)
87C1 XCHG AX,CX
87C8 XCHG CX,AX

next test.........
i dug up my old fave SymDeb - the c/l symbolic debugger that came with MASM 5.1
91     XCHG AX,CX
87C1 XCHG AX,CX
87C8  XCHG CX,AX


you will not be able to code XCHG CX,AX with MASM because it optimizes it into 1-byte (at least, it's supposed to)
but......
db 91h
db 87h,0C1h
db 87h,0C8h
then look at it with Olly


I have the Intel Manual right here
it is about as clear as mud
I am trying to decode it................
Title: Re: Olly and test
Post by: PauloH on May 09, 2009, 02:40:16 AM
Hi guys.
I tried the IDA disassembler, freeware edition and the results are changed too... the masm output matches the source code and the goasm output doesn't!!!
The attached files have .jpg files with the results. There are the sources I have used.
The confusion grows a little.
Kind regards.

[attachment deleted by admin]
Title: Re: Olly and test
Post by: redskull on May 09, 2009, 02:41:15 AM
It's a bug in masm.  As per the Intel manual, TEST ecx, eax is:

TEST r/m32, r32 should encode to 85 /r

where /r is

mod (11), reg32 (000), and r/m32 (001).  You put them together and get C1 for the second byte, which MASM encodes as C8 (and vice versa for the other way).  This comes from volume 2A, table 2-2 (though my intel manual is old) and figure 2-1.  Just to verify it:


From MASM:

00000001  85 C8   test ecx, eax   ; ecx in front
00000003  85 CB   test ecx, ebx
00000005  85 CA   test ecx, edx
00000007  85 CF   test ecx, edi
00000009  85 CE   test ecx, esi
0000000B  85 CD   test ecx, ebp
0000000D  90   nop
0000000E  85 C1   test eax, ecx   ; ecx behind
00000010  85 D9   test ebx, ecx
00000012  85 D1   test edx, ecx
00000014  85 F9   test edi, ecx
00000016  85 F1   test esi, ecx
00000018  85 E9   test ebp, ecx


from NASM

    26 0000000E 85C1                      test ecx, eax   ; ecx in front
    27 00000010 85D9                      test ecx, ebx
    28 00000012 85D1                      test ecx, edx
    29 00000014 85F9                      test ecx, edi
    30 00000016 85F1                      test ecx, esi
    31 00000018 85E9                      test ecx, ebp
    32 0000001A 90                        nop
    33 0000001B 85C8                      test eax, ecx   ; ecx behind
    34 0000001D 85CB                      test ebx, ecx
    35 0000001F 85CA                      test edx, ecx
    36 00000021 85CF                      test edi, ecx
    37 00000023 85CE                      test esi, ecx
    38 00000025 85CD                      test ebp, ecx


Olly is right, MASM generates the wrong opcodes.  Of course, since it just AND's then together, they're functionally equivalent (I think)

-ac
Title: Re: Olly and test
Post by: PauloH on May 09, 2009, 02:43:52 AM
This is the file with goasm output.


[attachment deleted by admin]
Title: Re: Olly and test
Post by: dedndave on May 09, 2009, 03:27:25 AM
thanks Paulo and RedSkuill - lol
i could not find the field definitions - i hate reading out of PDF's
it makes me wonder how they put AND together without trouble
MASM must be a box of band-aides - lol
Title: Re: Olly and test
Post by: BlackVortex on May 09, 2009, 04:26:57 AM
So the moral of the story is that an assembler may lie, but a disassembler ... NEVER !!!

Right ?  :green2
Title: Re: Olly and test
Post by: dedndave on May 09, 2009, 10:23:18 AM
lol - you have a point, there
the guys that take stuff apart are more intense about getting it right than the ones that put it together

the moral of the story is
Billy Gates lies as well as politicians

the one MS group i trusted was the assembler guys
my innocence is gone, now  :(

on the bright side, nice to see that Olly and the GoAsm guys are on their toes   :U
Title: Re: Olly and test
Post by: jj2007 on May 09, 2009, 11:14:28 AM
Quote from: dedndave on May 09, 2009, 10:23:18 AM

my innocence is gone, now  :(


It's never too late, Dave :wink

I like Masm. It's a bad-mannered animal, but its macro capabilities are a strong point. You can write your own version of Fortran, Basic or Perl, and its pure Masm - M for macro, but the code is assembler...

Kudos to the guys who designed Masm, in case they are still around.
Title: Re: Olly and test
Post by: dedndave on May 09, 2009, 11:49:45 AM
i haven't used macros much at all
except - long ago, i wrote a math library for 8088 with no 8087
for that, i used macros and a lot of conditional assembly for the different memory models
i think it was more of a lesson in MASM than math
i have forgotten all that stuff

you would think that, with my experience with ASM, it would be easy to learn 32-bit
but, i am struggling with
all the new pentium instructions
all the new MASM directives
learning Windows API, etc

yah - i think that's just everything - lol

i feel sorry for those who are trying to learn assembler anew
it was much easier in the 8088 days
Title: Re: Olly and test
Post by: Jimg on May 09, 2009, 02:33:08 PM
My reading of the instruction definition says masm and debug are right, and olly is wrong, despite how redskull interpreted it.
Title: Re: Olly and test
Post by: redskull on May 09, 2009, 03:43:14 PM
Here's my interpretation which is, of course, always subject to error.  I'm using the June 2005 version of the Intel manual.  From Volume 2A, Figure 2-1, the first byte is the opcode, and the second byte, labeled ModR/M, breaks down like this:

Mod field: bits 7-6
Reg/Opcode field: 5-3
R/M field: 2-0

From Volume 2B, the "TEST r/m32, r32" instruction is encoded as "85 /r".  In the case of "TEST ECX, EAX", that means eax would be the 'r32', and ecx would be the 'r/m32'.

Going back to volume 2A, table 2-2, section 2.1.5.  I found ECX row in the "Effective Address" Column (7th from the bottom), and then followed it over to the 'EAX' column.  They meet at the 'C1' value, which is what NASM encoded it as, but not MASM.
Just to make sure I matched up the columns right, in the second paragraph it states:

...the Effective Address column lists 32 effective addresses that can be assigned to the first operand of an instruction..

and

... this row (REG=) specifies the use of the 3-bit Reg/Opcode field when the field is used to give the location of a second operand..

I'm pretty certain that means the first operand (ECX) is down the left, and the second (EAX) is across the top.  Comments/Criticisms?  I have been known to mix things up before...

-r


Title: Re: Olly and test
Post by: dedndave on May 09, 2009, 06:51:14 PM
somewhere, i remember seeing some code where the source register was on the left
i don't think it was intel asm86 or masm, though

many of these instructions have 2 (or possibly more) valid op-codes
i.e. there is more than one way to code the same instruction

using TEST (or XCHG, for that matter) leaves it up in the air, as the instruction performs the same task either way

the ModR/M byte, in these cases, has three fields, Mod, reg, R/M
this could be a little confusing, as it is refered to as the "Mod R/M" byte, but the "reg" field is sandwiched between the two others

Mod field - bits 7,6
reg field - bits 5,4,3
R/M field - bits 2,1,0

reg or R/M for EAX=000 binary
reg or R/M for ECX=001 binary
if ECX is specified in the reg field, and EAX is specified in the R/M field, the lower nibble will be 8
if EAX is specified in the reg field, and ECX is specified in the R/M field, the lower nibble will be 1

for the TEST opcode 85, the destination register is specified in the R/M field

85 C1  TEST ECX,EAX
85 C8  TEST EAX,ECX

as a note of interest, the AND instruction has one form where the destination register is specified
in the R/M field and another form where the destination register is specified in the reg field
this may be how MASM coded it wrong - they grabbed the wrong table

21 AND r/m,reg
23 AND reg,r/m

Olly is right - MASM is wrong
I have attached pix from the Intel manual


[attachment deleted by admin]
Title: Re: Olly and test
Post by: Jimg on May 09, 2009, 06:55:01 PM
I look at it this way-

if I code
test ecx, eax
  and ecx, eax
  add ecx, eax
  xor ecx, eax

I get                                   
                                 
000001AD  85 C8   test ecx, eax       
000001AF  23 C8    and ecx, eax       
000001B1  03 C8    add ecx, eax       
000001B3  33 C8    xor ecx, eax       
in the listing.                 
                                       
If I look at olly, it says-             
                                 
004011AD   85C8    TEST EAX,ECX         
004011AF   23C8    AND ECX,EAX         
004011B1   03C8    ADD ECX,EAX         
004011B3   33C8    XOR ECX,EAX         
                                 
The intel manual says:                 

03 /r ADD  r32,r/m32   Add r/m32 to r32
23 /r AND  r32,r/m32   r32 AND r/m32
85 /r TEST r/m32,r32   AND r32 with r/m32; set SF, ZF, PF according to result

It seems pretty clear to me, but I could be wrong.
Title: Re: Olly and test
Post by: redskull on May 09, 2009, 07:47:11 PM
Exactly; your quote from the intel manual shows that for ADD and AND (at least the 03 and 23 versions of them) take the reg32 first and r/m32 second; the TEST opcode is the reverse.  So, if they all have the same second byte in the binary, TEST should dissassemble to the exact opposite of the ADD and AND, which Olly shows.  Had MASM encoded the ADD as '01' instead of '03', the order of the ADD would match the order of TEST.

-r

**EDIT*** Just to keep on ranting:  AND and ADD both have two different opcodes for register/register operation

01 - ADD r/m32, r32
03 - ADD r32, r/m32

21 - AND r/m32, r32
23 - AND r32, r/m32

whereas TEST only has one:

85 - TEST r/32, r32

So, if MASM choose to encode ADD and AND as 01 and 21, respectivley (where the order of the operands match that of TEST), then the same parameter order should have the same dissassembly.  If MASM choosed the 03 and 23 versions, in which the order is opposite of TEST, then the same paramaters should produce different second bytes, which it didn't.
Title: Re: Olly and test
Post by: Jimg on May 09, 2009, 08:54:19 PM
In the interest of sanity, I'm going to conceed at this point.  We need an Intel cpu engineer to really know how it actually works.
Title: Re: Olly and test
Post by: dedndave on May 09, 2009, 09:36:46 PM
lol Jim
reading the PDF's gives me a headache

it would be great to have one of Intel guys in here
one of the core architects
i bet he could write some killer code, too
he could solve all our issues   :lol

btw - d/l my zip file
it is pretty easy to follow
i have red-lined the pics
Title: Re: Olly and test
Post by: MichaelW on May 09, 2009, 09:48:01 PM
I don't know which way it's supposed to be, but in my limited test MASM is the odd one.

test ecx, eax
test ecx, ebx
test ecx, edx
test eax, ecx
test ebx, ecx
test edx, ecx


GoAsm disassembled with DumpPE (based on Microsoft tools AFAIK) or DrWatson:

85c1  test  ecx,eax
85d9  test  ecx,ebx
85d1  test  ecx,edx
85c8  test  eax,ecx
85cb  test  ebx,ecx
85ca  test  edx,ecx


Gas disassembled with DumpPE (based on Microsoft tools AFAIK) or DrWatson:

85c1  test ecx,eax
85d9  test ecx,ebx
85d1  test ecx,edx
85c8  test eax,ecx
85cb  test ebx,ecx
85ca  test edx,ecx


DEBUG (32-bit clone, originally by Paul Vojta, now developed by japheth, version 1.14):

6685C1 TEST ECX,EAX
6685D9 TEST ECX,EBX
6685D1 TEST ECX,EDX
6685C8 TEST EAX,ECX
6685CB TEST EBX,ECX
6685CA TEST EDX,ECX


Masm disassembled with DumpPE (based on Microsoft tools AFAIK) or DrWatson:

85c8  test  eax,ecx
85cb  test  ebx,ecx
85ca  test  edx,ecx
85c1  test  ecx,eax
85d9  test  ecx,ebx
85d1  test  ecx,edx


Edit:

Tasm 3.1 disassembled with Turbo Debugger 3.1:

6685C8  test  eax,ecx
6685CB  test  ebx,ecx
6685CA  test  edx,ecx
6685C1  test  ecx,eax
6685D9  test  ecx,ebx
6685D1  test  ecx,edx


At least MASM isn't all alone.
Title: Re: Olly and test
Post by: dedndave on May 09, 2009, 11:23:11 PM
MASM and some of the MS debuggers are debuggy as well
Title: Re: Olly and test
Post by: Tedd on May 15, 2009, 03:14:36 PM
In the encoding of some instructions, bit 1 of the first byte (the 'd' bit) indicates which way around operand 1 and operand 2 should be interpreted - in the case of two register operands this effectively results in src,dest or dest,src.
If you look at the encoding for SUB, for example, there are actually two and they differ in just this d bit. However, for TEST there is only one encoding, because the other is taken by XCHG.
Anyway, the end result is that it's probably down to a nuance in the way ml produces the encodings for instructions (probably lookup tables, etc.) And since they're both functionally equivalent in the case of TEST, it's not a problem.
That said, it would be comforting to know that you actually get out the code for the instructions you put in.



SUB
0010 100w : 11 reg1 reg2
0010 101w : 11 reg1 reg2

TEST
1000 010w : 11 reg1 reg2

XCHG
1000 011w : 11 reg1 reg2

{w=0: 8-bit operands, w=1: 16/32-bit operands (16 in 16-bit code, 32 in 32-bit code)}

It seems ml defaults to d=1, so the encoding appears backwards for TEST because it requires d=0.
Title: Re: Olly and test
Post by: dedndave on May 15, 2009, 03:21:36 PM
cool Tedd
i saw that on "AND" (21/23h)
i did not think to see if that bit was the direction bit for other op-codes
it makes sense, though
the guys at intel that lay these out are pretty sharp, i guess
who knows - they may use some kind of program to help them
they made some good choices early on with the 8086/8088
i suppose they made some bad ones, too
hard to have a crystal ball and predict future requirements
processor architecture has come a long way in 30 years
come to think of it, if i were to make a list of areas
where development has accelerated the most over that period,
microprocessor architecture would have to be near the top