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? ::)
Nice discovery !!! :green
I use Olly a lot and I never noticed.
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
Hi jj2007,
Which is the version of your Ollydbg copy?
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 ::)
huh ? :dazzled:
that makes no sense
my code goes one direction and EIP goes the other ? - lol
now, i am REALLY new to asm
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
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
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
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
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
no diff
xchg ?
I assume you are asking for timing purposes, because it certainly doesn't matter functionally. So time it and find out :P
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
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
Hi Paulo,
The output matches the source code, no?
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
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 !
well, JJ checked the op-codes against references
so - must be Olly
it was confirmed by others, as well
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
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................
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]
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
This is the file with goasm output.
[attachment deleted by admin]
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
So the moral of the story is that an assembler may lie, but a disassembler ... NEVER !!!
Right ? :green2
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
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.
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
My reading of the instruction definition says masm and debug are right, and olly is wrong, despite how redskull interpreted it.
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
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]
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.
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.
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.
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
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.
MASM and some of the MS debuggers are debuggy as well
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.
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