I wanted to find a clever way to zero eax without changing flags and tried
lea eax, dword ptr - [/b]
The trick works but is 5 bytes long (67:8D06 0000), and according to Olly it's called lea eax, [small 0]
:bg
Microsoft (R) Macro Assembler Version 6.15.8803 03/12/11 06:44:16
test83.asm Page 1 - 1
.386
.MODEL FLAT
00000000 .CODE
00000000 B8 00000000 mov eax,0
00000005 6A 00 push 0
00000007 58 pop eax
00000008 67& 8D 06 0000 lea eax,byte ptr [0]
END
Quote from: jj2007 on March 12, 2011, 11:46:29 AM
I wanted to find a clever way to zero eax without changing flags and tried lea eax, dword ptr - [/b]
The trick works but is 5 bytes long (67:8D06 0000), and according to Olly it's called lea eax, [small 0]
:bg
:bg
4 bytes:
pushfd
xor eax,eax
popfd
m2m eax, 0 is three bytes (Clive), the pushfd trick is a good one for delaying a loop that is too fast, but well, I made it in two bytes in the end. There is always some xor reg32, reg32 around, so push reg32/pop eax does the job in two bytes ;-)
Anyway, the [small 0] in Olly got my attention. Googling didn't yield any results, so I wonder if Olly invented this one. Especially since ML.exe says lea eax, dword ptr [small 0] deserves error A2206:missing operator in expression ::)
Quote from: jj2007 on March 12, 2011, 02:39:09 PM
Anyway, the [small 0] in Olly got my attention. Googling didn't yield any results, so I wonder if Olly invented this one. Especially since ML.exe says lea eax, dword ptr [small 0] deserves error A2206:missing operator in expression ::)
Can't say I've heard of the address override being referred to as small. Though short/small/near do make sense as a way to infer alternate encoding strategies. The 68K has the .L and .W directives for overriding the assembler's default/optimal encodings.
Some more observations:
lea eax, fs:[0] ; 8D05 00000000 lea eax, [0]
lea eax, dword ptr [0] ; 67:8D06 0000 lea eax, [small 0]
lea eax, word ptr [0] ; 67:8D06 0000 lea eax, [small 0]
lea eax, byte ptr [0] ; 67:8D06 0000 lea eax, [small 0]
The last three are all encoded as 67& 8D 06 0000, in ml 6.14, 6.15 and 9.0
In contrast, JWasm doesn't like it: 3*Error A2049: Invalid instruction operands
Avoid using the old 16 bits style address modes in 32 bits (ie avoid using the 0x67 prefix)... because it is slow and the 16 bits addressing mode (aka ModRM) is less flexible than the 32 bits one.
:bg
JJ,
I know this may be senile decay, not reading the topic until after lunch time etc but if zeroing EAX without changing the flags is the task, what is wrong wioth MOV EAX, 0 ?
push 0 / pop eax is the smallest way i can think of
it may be a little faster if you put some other instruction between them :P
Quote from: hutch-- on March 13, 2011, 01:03:37 AMif zeroing EAX without changing the flags is the task, what is wrong wioth MOV EAX, 0 ?
Hutch, in spite of the prominent role of The Colosseum, this is still
basically an assembler forum, so #define WIN32_LEAN_AND_MEAN :bdg
Quote from: dedndave on March 13, 2011, 02:12:44 AM
push 0 / pop eax is the smallest way i can think of
Dave, as I wrote earlier, if you search long enough before the line where you need the zeroed eax, there is always an xor edx, edx hanging around, so push edx/pop eax does the job in two bytes. Maybe in the innermostest of all loops you could use mov eax, 0, but for normal use push/pop is simply the best solution :bg
Quote from: jj2007 on March 13, 2011, 08:13:56 AMthere is always an xor edx, edx hanging around, so push edx/pop eax does the job in two bytes. Maybe in the innermostest of all loops you could use mov eax, 0, but for normal use push/pop is simply the best solution :bg
Personally,I'd use just the two byte MOV EAX,EDX, and not bother with a trip to the stack.
:bg
#define WIN32_LEAN_AND_MEAN
If that means 2 instruction fetches instead of one with MOV EAX, 1, I will stick to the bloat. Those 3 bytes will explode your hard disk. :P
Quote from: clive on March 13, 2011, 12:08:15 PM
Quote from: jj2007 on March 13, 2011, 08:13:56 AMthere is always an xor edx, edx hanging around, so push edx/pop eax does the job in two bytes. Maybe in the innermostest of all loops you could use mov eax, 0, but for normal use push/pop is simply the best solution :bg
Personally,I'd use just the two byte MOV EAX,EDX, and not bother with a trip to the stack.
The xor edx, edx happens several lines earlier:
xor edx, edx
push edx ; we need a zero...
.repeat
...
.Break .if Sign?
...
inc edx
.Until edx>=123
pop eax ; ... here
.if Sign?
... do stuff, ret non-zero eax
; implicit else:
; ret zero in eax
.endif
i doubt that the fetch is a big issue - you either have to fetch 5 bytes, or you have to fetch 3 - lol
i can see where it makes a difference if it occurs several times - it is just more efficient to find a brief method
if it is going to be used repeatedly, put a 0 in EBX, EBP, ESI, or EDI and leave it there throughout the routine
in a program i am working on, i do this in the "main" routine, in the "wmCreate" routine, and throughout most of the "init" routine
it doesn't just apply to 0 - it applies to any value that is going to be used over and over
whether speed or size are critical or not - it does not hurt to use an efficient method
we write in assembler, in part, because we get to control such things
Dave,
That is fine on an 8088 but the world has changed since 1980, pipelines, instruction queues and scheduling left that stuff behind long long ago. Instructions go through a pipeline AS instructions, not sequential bytes so the instruction count id a lot more important than the byte length.