Hi All:
What's the quickest way to find if EBX is Odd
or even?
isOdd proc
push ebx
and ebx, 1
pop ebx
ret
isOdd endp
Regards herge
Not bad, really, but why so complicated?
include \masm32\include\masm32rt.inc
.code
start: mov ebx, 123
test ebx, ebx
.if parity?
print str$(ebx), " is odd"
.else
print str$(ebx), " is even"
.endif
print chr$(13, 10, "That was short and crispy, right?")
getkey
exit
end start
:bg
Parity is the total number of bits on being odd or even, not the number itself. However, just "test ebx,1", .if zero? then even will work.
Quote from: Jimg on October 13, 2008, 02:01:13 PM
Parity is the total number of bits on being odd or even, not the number itself. However, just "test ebx,1", .if zero? then even will work.
I feel embarrassed :red
Thanxalot, Jim.
Hi All:
; BIT0.ASM Monday, October 13, 2008 11:18 AM
include \masm32\include\masm32rt.inc
.code
start: mov ebx, 122
mov ecx, 12
Next:
test ebx, 1
push ecx
.if zero?
print str$(ebx), " is Even"
.else
print str$(ebx), " is Odd"
.endif
print chr$( 13, 10)
pop ecx
inc ebx
dec ecx
jnz Next
print chr$(13, 10, "That was short and crispy, right?")
getkey
exit
end start
Regards herge
How about using mod to determine if odd or even? something like this:
_mod MACRO val1:REQ, val2:REQ
push ecx
mov eax,val1
mov ecx,val2
xor edx,edx
div ecx
pop ecx
exitm <edx>
endm
Given that all odd numbers return a 1 when divided by 2, and even numbers return 0:
.IF _mod(ebx,2) == 0
; even
.ELSE
; odd
.ENDIF
Quote
How about using mod to determine if odd or even?
DIV is many times slower than test eax,1 :D
Quote from: fearless on October 13, 2008, 03:51:53 PM
How about using mod to determine if odd or even? something like this:
..
Given that all odd numbers return a 1 when divided by 2, and even numbers return 0:
That sounds interesting and innovative. Given that div is a relatively slow instruction, as Bogdan rightly notes, could we optimise it by replacing the div with a multiply? Here is a first attempt, it seems to work perfectly:
123 is odd
122 is even
121 is odd
120 is even
119 is odd
118 is even
117 is odd
116 is even
115 is odd
include \masm32\include\masm32rt.inc
.data?
f2sConW dw ?
.code
Point5 REAL10 0.5
start:
fstcw f2sConW ; status word could be saved as fstsw ax,
mov ax, f2sConW ; but no such instruction for Control word
or ax, 011100000000b ; rounding mode DOWN,
mov f2sConW, ax ; precision max=64
fldcw f2sConW ; set new control word
mov ebx, 123
.While ebx>100
push ebx
fild dword ptr [esp] ; push an integer (reg or immediate)
fld Point5
fmul
frndint
fadd st, st
fild dword ptr [esp]
fsub
fistp dword ptr [esp]
pop eax
inc eax
.if zero?
print str$(ebx), " is odd", 13, 10
.else
print str$(ebx), " is even", 13, 10
.endif
dec ebx
.Endw
print chr$(13, 10, "That was short and crispy, right?")
getkey
exit
end start
No way... MUL is also very slow when compared with TEST :D
Basically the bitwise operators: AND, XOR, OR, NOT and TEST(hidden AND) are the fastest operations that electronics can do on a register. You can not get much faster than this because it is just a single gate with 2 inputs performing the operation... anything else is slower ...
Quote from: BogdanOntanu on October 13, 2008, 04:27:52 PM
No way... MUL is also very slow when compared with TEST :D
Hey Bogdan, where is your sense of humour???
AI_FLAG_HAS_HUMOR EQU 1
test eax,AI_FLAG_HAS_HUMOR
.IF zero?
invoke On_Humor,LIFE_CTX
.ENDIF
ret
I think I have missed a JNZ somewhere .. :D
Hi ALL:
Rotating the wrong way thru carry.
; ODD.ASM Monday, October 13, 2008 6:50 AM
include \masm32\include\masm32rt.inc
.data
buf dd 0
evenA db " Even ", 13, 10, 0
odd db " Odd ", 13, 10, 0
buffer db 20 dup(0)
db 0
.code
isOdd proc
push ebx
rcr ebx, 1
pop ebx
ret
isOdd endp
printEbx proc
push ebx
push ecx
push edi
invoke crt__ultoa, ebx, buf, 10
invoke StdOut, offset buffer
pop edi
pop ecx
pop ebx
ret
printEbx endp
.code
Start:
lea eax, offset buffer
mov buf, eax
mov ecx, 25
mov ebx, 1
@@:
call printEbx
call isOdd
jnc isEven
push ebx
push ecx
invoke StdOut, addr odd
pop ecx
pop ebx
jmp Next
isEven:
push ebx
push ecx
invoke StdOut, addr evenA
pop ecx
pop ebx
Next:
inc ebx
dec ecx
jnz @B
inkey
exit
ret
end Start
The div instruction is going to slow I can remember doing biniary
to Ascii Decimal before we had the div instruction!
Regards herge
Folks, this thread is getting increasingly odd.
Hi jj2007:
It is suppose to be ODD or EVEN so
far!
Regards herge
Use AND and BT. Odd numbers expressed in binary always have the rightmost (2^0) bit = 1 and even numbers always have the 2^0 bit = 0.
IsEven MACRO val1:REQ
push eax
mov eax, val1
and eax, 1
bt eax, 0 ; test lowest bit
jnc Even ; jmp if bit is 0
:Odd
mov edx, FALSE
jmp OddEvenEnd
:Even
mov edx, TRUE
OddEvenEnd:
pop eax
exitm <edx>
ENDM
:eek why AND ?
EDIT :
you can reduce your macro to something like :
IsEven MACRO val1:REQ
xor edx,edx ; edx = 0
bt val1,0 ; test lowest bit
adc edx,edx ; edx = 0+carry
btc edx,0 ; invert bit 0
ENDM
and deduce this macro :
IsOdd MACRO val1:REQ
xor edx,edx ; edx = 0
bt val1,0 ; test lowest bit
adc edx,edx ; edx = 0+carry
ENDM
Quote from: NightWare on October 14, 2008, 12:32:50 AM
you can reduce your macro to something like :
IsEven MACRO val1:REQ
xor edx,edx ; edx = 0
bt val1,0 ; test lowest bit
adc edx,edx ; edx = 0+carry
btc edx,0 ; invert bit 0
ENDM
EVEN that is much too ODD for my taste. Since there is a small risk that noobs read this thread, here is the final solution (see herge's reply #4):
mov ebx, 123
test ebx, 1
.if zero?
print str$(ebx), " is even", 13, 10
.else print str$(ebx), " is odd", 13, 10
.endifFor the noobs: Some of the earlier posts were written with the agenda "how can I perform simple things in the most complicated way".
For the moderators: Please introduce a smiley saying "Attention, I am pulling your leg" :lol
wow...just...wow
I can't believe the effort that has gone into this topic, all for a "test ebx,1".
The best was introducing edx, but second prize has to go to using all these bt/btc opcodes...
My offering
test ebx,1 ;test bl,1
jnz is_oddly_an_odd_number ;you know, 1,11,101,111,1001 ad infinitum
;code here for even number
Hey, this is like the "destructive AND vs non-destructive TEST" thing, isn't it. :bg
Quote from: sinsi on October 14, 2008, 06:17:19 AM
The best was introducing edx, but second prize has to go to using all these bt/btc opcodes...
I am deeply disappointed that you chose to ignore my simple FPU solution, #7.
QuoteHey, this is like the "destructive AND vs non-destructive TEST" thing, isn't it. :bg
How odd that you even thought of that thread :green
Quote from: sinsi on October 14, 2008, 06:17:19 AM
wow...just...wow
I can't believe the effort that has gone into this topic, all for a "test ebx,1".
The best was introducing edx, but second prize has to go to using all these bt/btc opcodes...
My offering
test ebx,1 ;test bl,1
jnz is_oddly_an_odd_number ;you know, 1,11,101,111,1001 ad infinitum
;code here for even number
Hey, this is like the "destructive AND vs non-destructive TEST" thing, isn't it. :bg
For sure, some of this board topics are just fascinating. :cheekygreen:
Still waiting for the sse2 version though.
Quote from: sinsi on October 14, 2008, 07:03:22 AM
Still waiting for the sse2 version though.
And the code timing because we are still not sure by how many cpu clocks "test ebx,1" will beat them all :green2
I think I've got the slowest one. Usually takes a few seconds, but can occasionally take a number of hours, depending on how complicated the number is:
IsOdd PROC number:DWORD
LOCAL buffer:BYTE[256]
lea eax, buffer
mov BYTE PTR [eax], 0
mov eax, cat$(eax, "Is the number ", ustr$(number), " an odd number?")
invoke MessageBoxA, 0, eax, chr$("Odd or even?"), MB_YESNO OR MB_ICONQUESTION
.if(eax == IDYES)
mov eax, TRUE
.else
mov eax, FALSE
.endif
ret
IsOdd ENDP
Cheers,
Zooba :U
I haven't actually tested that code, and I don't normally use MASM32's string macros, so apologies if it is all wrong :bg
Considering that this is the Laboratory, you should create a speed-optimized version that displays only the value of the last bit. It would still run slow on some systems, but for most it should be much faster.
Quote from: zooba on October 14, 2008, 08:02:40 AM
I think I've got the slowest one. Usually takes a few seconds, but can occasionally take a number of hours, depending on how complicated the number is:
I did some timings, and the results look ODD, it EVEN seems there is some quadratic element:
number time
123 5'
1234 7'30''
4321 9'00''
12345678 3h30'00''
123454321 --- exception #5
Besides, your code failed miserably for the last number. Zooba, could you please post the complete source?
The thread is getting ODD, EVENthough we are only dealing with a simple algo here. :lol
Here's my little contribution. It's a good exercise for a masm32 starter like me. :P
main proc
LOCAL num1:DWORD
mov num1, sval(input("Enter a number : "))
mov ebx,num1
and al,1b ;logical operation.
cmp al,1
jne even1
je odd
odd:
print str$(ebx)," is odd"
jmp done
even1:
print str$(ebx)," is even"
done:
ret
main endp
It's hard to technically explain it but whenever your value is in odd bit-0 is always set to 1.
For example:
ODD
7d =0111b
15d=1111b
9d =1001b
EVEN
10d=1010b
6d = 0110b
This holds true with large values too. I guess this a matter of common sense nowadays. :U
All solution is accepted by the way. It's up to the user how to deal with them. If speed is a factor, then use bitwise operators.
here is an experienced coder contribution :))
.data
szeven db "EVEN",0
szodd db "ODD",0
align 4
msgs dd offset szeven,offset szodd
.code
mov eax,number
and eax,1
mov eax,[msgs+eax*4]
invoke MessageBox,0,eax,0,0
.data?
msgs db 8 dup (?)
.code
mov eax,number
and eax,1
cmp eax,1
sbb eax,eax; 0 if eax >= 1 else -1
and eax,"NEVE"-"DDO"
add eax,"DDO"
mov dword ptr msgs,eax
invoke MessageBox,0,addr msgs,0,0
Quote from: eaOn on October 14, 2008, 04:35:51 PM
and al,1b ;logical operation.
:lol
Quote from: MichaelW on October 14, 2008, 08:27:29 AM
Considering that this is the Laboratory, you should create a speed-optimized version that displays only the value of the last bit. It would still run slow on some systems, but for most it should be much faster.
:lol i have one !!! here => and eax,1
beside bogdan has said it's difficult to do it faster !
How about...
shr ebx,1
jc _odd_number_
Hi DommyD:
See reply #11 ( Page 1)
.code
isOdd proc
push ebx
rcr ebx, 1
pop ebx
ret
isOdd endp
Regards herge
Quote from: NightWare on October 14, 2008, 10:05:24 PM
Quote from: MichaelW on October 14, 2008, 08:27:29 AM
Considering that this is the Laboratory, you should create a speed-optimized version that displays only the value of the last bit. It would still run slow on some systems, but for most it should be much faster.
:lol i have one !!! here => and eax,1
beside bogdan has said it's difficult to do it faster !
NightWare, you should carefully read zooba's post in order to understand what Michael means with "systems" :lol
The kind of humour this topic is going throught made realize that we should free our hidden nerds inside... or die :green2
(http://i239.photobucket.com/albums/ff140/Javelin09/Nerds.jpg)
hi herge,
rol ebx,31
test ebx,ebx
js _odd_
:U
For a really fast method eliminate the branch
or ebx, 1
print "ebx is odd ", 0Dh, 0Ah
Regards Roger
Quote from: Roger on October 15, 2008, 11:13:14 AM
For a really fast method eliminate the branch
or ebx, 1
print "ebx is odd ", 0Dh, 0Ah
Regards Roger
:bg man, that is zen-like
print "ebx is either odd or even", 0Dh, 0Ah
Quote from: Roger on October 15, 2008, 11:13:14 AM
For a really fast method eliminate the branch
or ebx, 1
print "ebx is odd ", 0Dh, 0Ah
Regards Roger
Fast but not flexible enough!
.if NeedOdd
or ebx, 1
print "ebx is odd ", 0Dh, 0Ah
.elseif NeedEven
and ebx, 1111111111111110b
print "ebx is even ", 0Dh, 0Ah
.else
trash ebx
print "ebx is NaN ", 0Dh, 0Ah
.endif
Someone may like these two simple macros.
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
jevn MACRO value, label
mov eax, value
and eax, 00000000000000000000000000000001b
jz label
ENDM
jodd MACRO value, label
mov eax, value
and eax, 00000000000000000000000000000001b
jnz label
ENDM
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
mov eax, 99999992
jevn eax, nxt
print str$(eax)," odd",13,10
jmp quit1
nxt:
print str$(eax)," even",13,10
quit1:
mov eax, 12345
jodd eax, nxt1
print str$(eax)," even",13,10
jmp quit2
nxt1:
print str$(eax)," odd",13,10
quit2:
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
I think I've got a winner :green2push ebx
print "is ebx odd? let's find out =D",13,10
getkey
pop ebx
and ebx,1
div ebx
print "I guess it is =]",13,10
Quote from: hutch-- on October 15, 2008, 12:47:51 PM
Someone may like these two simple macros.
jevn MACRO value, label
mov eax, value
and eax, 00000000000000000000000000000001b
jz label
ENDM
Hutch, oh dear,
highly destructive code!!! You are not scared of the CPU police (http://www.masm32.com/board/index.php?topic=9619.msg70349#msg70349)??
Here are safe alternatives:
jevn MACRO value, label
test value, 1
jz label
ENDM
jodd MACRO value, label
test value, 1
jnz label
ENDM
print "ebx may be odd or even, but when you check the cat will be dead."
Now here's a nerdiness test. If you laugh at that... I've got bad news for you :toothy
:bg
> Hutch, oh dear, highly destructive code!!! You are not scared of the CPU police??
Yep, this is deadly srerious stuff.
I find it ODD that anyone is EVEN working on code for this... :bg
Hi zooba:
Do you mean Schrödinger's cat?
This is assembler ? not quantum
mechanics.
int main(int)
{
cout << "\t\t\tThe Fibonacci Series\n";
int X = 0;
for ( int i = 0; i < 7; i++ ) { /* row*/
for ( int j = 0; j < 6; j++, X++ ) { /* column */
if ( ( X & 1 ) == 1 ) cout << left; /* Odd */
else cout << right; /* Even */
cout << setw(10) << FibX(X) << " ";
}
if ( i == 6 ) break; /* last row ? : Exit */
cout << endl;
}
getch(); // Pause Wait for Keyboard
The Fibonacci Series
1 1 2 3 5 8
13 21 34 55 89 144
233 377 610 987 1597 2584
4181 6765 10946 17711 28657 46368
75025 121393 196418 317811 514229 832040
1346269 2178309 3524578 5702887 9227465 14930352
24157817 39088169 63245986 102334155 165580141 267914296
Regards herge
Quote from: jdoe on October 15, 2008, 06:45:53 AM
The kind of humour this topic is going throught made realize that we should free our hidden nerds inside... or die :
Good thing Schrödinger's cat wasn't a nerd or he, Schrödinger, would have been stuck.
Regards Roger
:lol
I laughed at some post.
There are so many ways to look for a value is it odd or even.
IsOdd proc value:dword
mov eax,value
and eax,1
ret
IsOdd endp
This one is the sortest I can get.
Here is example how to use it
Invoke IsOdd,1234567
.if eax==0
invoke MessageBox,0,CADD("Its Even"),0,0
.else
invoke MessageBox,0,CADD("Its Odd"),0,0
.endif
Farabi,
Your version is short but it alters eax. No need for that:
mov eax, 12345
test eax, 1 ; same as and eax, 1 but without actually changing the register
.if zero?
invoke MessageBox, 0, str$(eax), chr$("Even:"), MB_OK
.else
invoke MessageBox, 0, str$(eax), chr$("Odd:"), MB_OK
.endif
Quote from: jj2007 on October 17, 2008, 01:15:35 PM
mov eax, 12345
test eax, 1 ; same as and eax, 1 but without actually changing the register
.if zero?
invoke MessageBox, 0, str$(eax), chr$("Even:"), MB_OK
.else
invoke MessageBox, 0, str$(eax), chr$("Odd:"), MB_OK
.endif
jj, test reg,1 is NOT the fastest method... coz if test is fast in itself, you NEED a jump (je,jne,jz,jnz) to use it... so you will have a branch misprediction (except in speed test, or small app limited to this work...) look at drizz post to see how to do.
noobs, do not listen the macros lovers !!! they don't see what they are doing ! :lol
after software optimisations, we must pass to user optimisations, here how to proceed... in my opinion it's the GOTY, but guys, don't play at work... :lol
[attachment deleted by admin]
Hi NightWare:
Neat program!
ML.exe is usually in C:\masm32\bin
It is looking for RESOURCE.H on a F drive
I am pretty sure I don't have a F drive.
Microsoft (R) Windows (R) Resource Compiler, Version 5.00.1823.1 - Build 1823
Copyright (C) Microsoft Corp. 1985-1998. All rights reserved.
Using codepage 1252 as default
Creating rsrc.RES
RC: RCPP -CP 1252 -f C:\masm32\bin\odd\OddOrEven\RCa03888 -g C:\masm32\bin\odd\OddOrEven\RDa03888 -DRC_INVOKED -D_WIN32 -pc\:/ -E -I. -I . -I C:\Program Files\Microsoft SDK\Include\.
rsrc.rc(1) : fatal error RC1015: cannot open include file 'F:\Programmation\MAsm32\INCLUDE\RESOURCE.H'.
Microsoft (R) Windows Resource To Object Converter Version 5.00.1736.1
Copyright (C) Microsoft Corp. 1992-1997. All rights reserved.
CVTRES : fatal error CVT1101: cannot open rsrc.res for reading
Assembling: OddOrEven.asm
Microsoft (R) Incremental Linker Version 5.12.8078
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.
Volume in drive C has no label.
Volume Serial Number is 20B4-B172
Directory of C:\masm32\bin\odd\OddOrEven
10/17/2008 08:50 PM 11,478 OddOrEven.asm
10/17/2008 05:50 PM 1,594 OddOrEven.bat
10/17/2008 05:56 PM 4,096 OddOrEven.exe
05/06/2005 12:13 AM 727 OddOrEven.exe.manifest
10/17/2008 05:56 PM 4,388 OddOrEven.obj
5 File(s) 22,283 bytes
0 Dir(s) 218,251,354,112 bytes free
Press any key to continue . . .
Regards herge
Quote from: herge on October 17, 2008, 10:01:13 PM
Neat program!
ML.exe is usually in C:\masm32\bin
It is looking for RESOURCE.H on a F drive
I am pretty sure I don't have a F drive.
:red yep, sorry i've forgotten to change those path... i update the code as soon as i can...
Quote from: NightWare on October 17, 2008, 09:36:34 PM
jj, test reg,1 is NOT the fastest method... coz if test is fast in itself, you NEED a jump (je,jne,jz,jnz) to use it... so you will have a branch misprediction (except in speed test, or small app limited to this work...) look at drizz post to see how to do.
drizz's post gives correct results, but I don't think he was seriously proposing to squeeze out half a cycle for code that ends with a MessageBox.
Furthermore, I did not claim that test eax, 1 was the absolutely fastest way to do it. But it preserves all registers, is the shortest, and is usually pretty fast. By the way, in your post I missed timers.asm among the includes
Quote
noobs, do not listen the macros lovers !!! they don't see what they are doing ! :lol
Those who write macros need to understand every little detail of their code.
Quote
after software optimisations, we must pass to user optimisations, here how to proceed... in my opinion it's the GOTY, but guys, don't play at work... :lol
noob, don't trust people who send zip archives with nine files for a tiny little project. Especially if the code looks confused, and the exe is not working on XP.
Quote from: jj2007 on October 17, 2008, 11:25:52 PMThose who write macros need to understand every little detail of their code.
exactly !!!
Quote from: jj2007 on October 17, 2008, 11:25:52 PMnoob, don't trust people who send zip archives with nine files for a tiny little project. Especially if the code looks confused
confused ? in what ?
Quote from: jj2007 on October 17, 2008, 11:25:52 PMand the exe is not working on XP.
hey ! it's unfair, it's vista here ! not me... :lol
Quote from: NightWare on October 17, 2008, 11:46:40 PM
Quote from: jj2007 on October 17, 2008, 11:25:52 PMand the exe is not working on XP.
hey ! it's unfair, it's vista here ! not me... :lol
Actually, this was bothering me a lot, so I tested intensively why it didn't work:
- When I double-click on OddOrEven.exe in the archive,
it works.
- When I double-click on OddOrEven.exe in its folder,
it does not work.
The solution is... but why make things unnecessarily easy, after all, we are trying to replace test eax, 1 with something more sophisticated, right? So here is a riddle for you:
http://shell.windows.com/fileassoc/0409/xml/redir.asp?EXT=xxx <-guess which file type is unknown to Microsoft :toothy
File Type: Unknown
Description: Windows does not recognize this file type.
Hint: The code assembles fine without this file.
:bg
Ain't nuthin' wrong with macros. (AS LONG AS YOU UNDERSTAND THEM) :P
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
ifevn MACRO value
mov eax, value
test eax, 00000000000000000000000000000001b
ENDM
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
mov eax, 12345
ifevn eax
je nxt
print str$(eax)," odd",13,10
jmp quit1
nxt:
print str$(eax)," even",13,10
quit1:
mov eax, 123456
ifevn eax
jne nxt1
print str$(eax)," even",13,10
jmp quit2
nxt1:
print str$(eax)," odd",13,10
quit2:
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
Quote from: jj2007 on October 18, 2008, 12:10:39 AMhttp://shell.windows.com/fileassoc/0409/xml/redir.asp?EXT=xxx <-guess which file type is unknown to Microsoft :toothy
hmm, in fact the problem happen during uncompressing, it seams the old winzip version i use "hate" double extension... but it's strange it happen on xp (i already had the problem...) and not on vista...
Indeed. The archive contains a OddOrEven.exe.manifest
What is plain ridiculous is that
a) Windows XP cannot interpret the double extension correctly, a dozen years after the introduction of long filenames
b) when you lookup the "unknown" extension, M$'s own site has never heard of .manifest
Imho they lost already years ago control over their pile of.
Hi hutch:
Slightly less verbose:
ifevn MACRO value
mov eax, value
test eax, 1
ENDM
Regards herge
herge,
The reason for the binary notation is so you know what the macxro does, a TEST and mask without saving the results.
Quote from: herge on October 18, 2008, 02:10:48 AM
Slightly less verbose:
ifevn MACRO value
mov eax, value
test eax, 1
ENDM
Regards herge
There is no need to move the value into eax. Test value, 1 is sufficient.
include \masm32\include\masm32rt.inc
.data
VarOdd dd 12345
VarEven dd 123456
.code
start: test VarOdd, 1
jz @F
MsgBox 0, str$(VarOdd), "Odd:", MB_OK
jmp Test2
@@: MsgBox 0, str$(VarOdd), "Even:", MB_OK
Test2: test VarEven, 1
jz @F
MsgBox 0, str$(VarEven), "Odd:", MB_OK
jmp Test3
@@: MsgBox 0, str$(VarEven), "Even:", MB_OK
Test3: mov eax, 12345678
test eax, 1
jz @F
MsgBox 0, str$(eax), "eax is odd:", MB_OK
jmp Test4
@@: MsgBox 0, str$(eax), "eax is even:", MB_OK
Test4: exit
end start
It fails on "TEST IMMEDIATE, 00000000000000000000000000000001b"
Hi jj2007:
There is no need to move the value into eax. Test value, 1 is sufficient.
Thank you jj2007 one less op-code.
Regards herge
Quote from: hutch-- on October 18, 2008, 08:40:21 AM
It fails on "TEST IMMEDIATE, 00000000000000000000000000000001b"
You are perfectly right, Hutch. In these rare cases, the slow solution proposed here (http://www.masm32.com/board/index.php?topic=10109.msg74081#msg74081) by zooba must be applied.
:bg
Apart from the use of the register working in all cases, the averages for a MOV/TEST are much better than TEST MEM, IMMEDIATE and the very slow alternative.
Quote from: hutch-- on October 18, 2008, 11:23:51 AM
:bg
Apart from the use of the register working in all cases, the averages for a MOV/TEST are much better than TEST MEM, IMMEDIATE and the very slow alternative.
Much better?? I love hard facts, as you know (code attached):
0 cycles, eax odd
-2 cycles, VarOdd
0 cycles, VarEven
-1 cycles, mov eax, odd
0 cycles, mov eax, VarOdd
0 cycles, mov eax, VarEven
0 cycles, mov eax, immediate even
-1 cycles, mov eax, immediate odd
3 cycles, call IsOdd, odd
3 cycles, call IsOdd, VarOdd
3 cycles, call IsOdd, VarEven
3 cycles, call IsOdd, immediate even
3 cycles, call IsOdd, immediate odd
With regard to immediates, yes it's true that your jeven macro is the most flexible option:
jevn MACRO value, lbl
mov eax, value
test eax, 1
jz lbl
ENDM
.code
mov eax, 123
jevn eax, L1
nop
L1:
jevn 123, L2
nop
L2:
However, in pseudocode the jevn 123, L2 can be expressed as:
.if 123==odd
nop
.endif
An experienced coder (20 years of experience should be enough, I guess) might notice that the immediate value 123 is, in the great majority of cases,
odd; therefore the snippet could be shortened as follows:
; .if 123==odd
nop
; .endif
[attachment deleted by admin]
Hi jj2007:
The results of your program on my computer.
0 cycles, eax odd
0 cycles, VarOdd
0 cycles, VarEven
0 cycles, mov eax, odd
0 cycles, mov eax, VarOdd
0 cycles, mov eax, VarEven
0 cycles, mov eax, immediate even
0 cycles, mov eax, immediate odd
2 cycles, call IsOdd, odd
2 cycles, call IsOdd, VarOdd
3 cycles, call IsOdd, VarEven
3 cycles, call IsOdd, immediate even
2 cycles, call IsOdd, immediate odd
Press any key to continue ...
Regards herge
:bg
Its surprising what you learn from manually optimising C compiler output. There is an old P1/PII optimisation still done by many C compilers where a value is translated into a register first before performing the operation. Spend the time to remove the register transfer on the complete algo and you pick up a ZERO speed increase. The only reason why you bother is to free up registers.
Now the obvious is that the macro line,
mov eax, value
can be used in all 3 forms,
mov eax, REG
mov eax, MEM
mov eax, IMMEDIATE
which is why you bother to write the macro in that form. Unless the code was in the middle of a truly speed critical algorithm, it will do the job fine and easily as fast as a direct memory operation. the exceptions occur when you "may" get a better encoding by changing the entire instruction sequence.
herge,
look at the timing values to see why the test is meaningless with that duration, the test needs to be done in an appropriate context for about 500ms or longer to get stable results.
jj,
Quote
An experienced coder (20 years of experience should be enough, I guess) might notice that the immediate value 123 is, in the great majority of cases, odd; therefore the snippet could be shortened as follows:
Spot the diference.
mov eax, 1111011b
mov eax, 7Bh
mov eax, 123
Quote from: hutch-- on October 18, 2008, 02:53:03 PM
look at the timing values to see why the test is meaningless with that duration, the test needs to be done in an appropriate context for about 500ms or longer to get stable results.
I fleshed it up a little bit:
420 cycles, test xxx, 1
551 cycles, mov eax, xxx, test eax, 1
Quote
Spot the diference.
mov eax, 1111011b
mov eax, 7Bh
mov eax, 123
Hmmm....? First, you don't use the spell-checker any more; second, they are all odd. Otherwise, no idea what you mean.
By the way, there is one situation where the mov eax, xxx is indeed needed:
mov eax, [esp]
test eax, 1
In all other cases, the mov eax just wastes a register and costs some space.
[attachment deleted by admin]
:bg
here are results from 3 tests. The mov/test is never slower but will handle all cases, the optimised register version is more than twice as fast and the test on a memory operand brings up the tail as being not as flexible and not as fast as the pure register/immediate version.
1109 ; 1st test
454 ; second test
1109 ; third test
Press any key to continue ...
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
comment * -----------------------------------------------------
Build this template with
"CONSOLE ASSEMBLE AND LINK"
----------------------------------------------------- *
.code
start:
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
call main
inkey
exit
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
main proc
LOCAL value :DWORD
invoke SetPriorityClass,rv(GetCurrentProcess),HIGH_PRIORITY_CLASS
push esi
; ---------------------------------
invoke GetTickCount
push eax
mov esi, 500000000
@@:
mov eax, 12345678
test eax, 00000000000000000000000000000001b ; test the end bit
mov eax, 12345678
test eax, 00000000000000000000000000000001b ; test the end bit
mov eax, 12345678
test eax, 00000000000000000000000000000001b ; test the end bit
mov eax, 12345678
test eax, 00000000000000000000000000000001b ; test the end bit
sub esi, 1
jnz @B
invoke GetTickCount
pop ecx
sub eax, ecx
print str$(eax),13,10
; ---------------------------------
invoke SleepEx,200,0
; ---------------------------------
invoke GetTickCount
push eax
mov esi, 500000000
mov eax, 12345678
@@:
test eax, 00000000000000000000000000000001b ; test the end bit
test eax, 00000000000000000000000000000001b ; test the end bit
test eax, 00000000000000000000000000000001b ; test the end bit
test eax, 00000000000000000000000000000001b ; test the end bit
sub esi, 1
jnz @B
invoke GetTickCount
pop ecx
sub eax, ecx
print str$(eax),13,10
; ---------------------------------
invoke SleepEx,200,0
; ---------------------------------
invoke GetTickCount
push eax
mov esi, 500000000
mov value, 12345678
@@:
test value, 00000000000000000000000000000001b ; test the end bit
test value, 00000000000000000000000000000001b ; test the end bit
test value, 00000000000000000000000000000001b ; test the end bit
test value, 00000000000000000000000000000001b ; test the end bit
sub esi, 1
jnz @B
invoke GetTickCount
pop ecx
sub eax, ecx
print str$(eax),13,10
; ---------------------------------
invoke SetPriorityClass,rv(GetCurrentProcess),NORMAL_PRIORITY_CLASS
pop esi
ret
main endp
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
end start
1593
938
1563
1562 4)
4)
REPEAT 4
mov eax, value
test eax, 00000000000000000000000000000001b ; test the end bit
Difference on my Celeron M is not as dramatic, but it still confirms:
- test exx, 1 is a lot faster than the indirect version
- mov eax, value plus test eax, 1 is never faster than the direct test value, 1
So we can safely use the shortest version :green
Hi hutch:
704
437
860
Press any key to continue ...
Results of your program on my computer.
Regards herge
:bg
> So we can safely use the shortest version
If you don't mind it failing on the immediate. The idea of the macro was to be general purpose which it is but with no speed penalty. Manual coding options allow you to different things in different contexts but for general purpose, the reg load then TEST is more flexible and as fast.
herge,
What processor are you using ? Mine was done on my old PIV, my other two more or less agree and I know JJ is using a celeron.
Quote from: hutch-- on October 18, 2008, 11:13:31 PM
:bg
> So we can safely use the shortest version
If you don't mind it failing on the immediate.
In general, an .if 123==odd doesn't make sense. An immediate is either odd or even, and you know it already at assembly time, not at runtime. The only exception would be self-modifying code :wink
Quote
for general purpose, the reg load then TEST is more flexible and as fast.
as fast, except if
value is a register - a frequent case...
As you know, I am a great fan of macros, but in this case I vote for the (almost) plain assembler:
test RegOrMem, 1
.if zero?
print "is even"
.else
print "is odd"
.endif
Hi hutch:
I have a duo core.
Processor: Intel(R) Core(TM)2 Duo CPU E4600 @ 2.40GHz (2 CPUs)
Regards herge
Hi Herge,
Quote from: herge on October 18, 2008, 11:24:59 PM
I have a duo core.
Processor: Intel(R) Core(TM)2 Duo CPU E4600 @ 2.40GHz (2 CPUs)
Does this mean that
ebx is odd
ebx is even
can both be true at the same time? ::)
Regards Roger
Hi Roger:
I suspect the answer is going to be yes!
When it will be yes I don't knew.
They are trying to build computers that
can be both on and off at the same time.
Regards herge
JJ,
I ask the question on the example for a reason.
; hex 7Bh
; bin 1111011
; dec 123
They are all the same number but in different radix. Decimal is easy but for a vast number of people hex and binary are not.
The idea of a general purpose macro is that it IS general purpose, as soon as you make exceptions you may as well code it manually.
Try this one.
; --------------------
mov value, 3
mov ecx, 2
mov eax, value
test eax, 00000000000000000000000000000001b ; test trailing bit.
cmovnz eax, ecx
print str$(eax),13,10
; --------------------
Quote from: hutch-- on October 19, 2008, 07:19:54 AM
Decimal is easy but for a vast number of people hex and binary are not.
You are right. Remember I always take the side of the noobs, so a cute simple little macro may really be the best solution. What about this one?
include \masm32\include\masm32rt.inc
odd MACRO value
mov eax, value
and eax, 1
EXITM <eax>
ENDM
.code
start:
.if odd(123)
print "123 is odd"
.else
print "Hooray, I just won the Nobel Prize in mathematics!"
.endif
getkey
exit
end start
Would I really get the Nobel prize in mathematics ? :bg
It looks OK but I would still use the binary notation instead of 1 so that the viewer knew what was being done with the AND/TEST mask.
Hi Hutch,
Quote from: hutch-- on October 19, 2008, 07:19:54 AM
They are all the same number but in different radix. Decimal is easy but for a vast number of people hex and binary are not.
What you need is a 4-function calculator that works in any radix and converts between them.
Regards Roger
Roger,
Windows CALC comes pretty close.
Quote from: hutch-- on October 19, 2008, 12:57:54 PM
Would I really get the Nobel prize in mathematics ? :bg
...
:bg You will, so do I because I help clean your cloth and serve you a coffee.
Quote from: Roger on October 19, 2008, 11:58:40 PM
What you need is a 4-function calculator that works in any radix and converts between them.
What? All assembly programmers don't think in binary? :wink
Hi All:
So the end result is:
if ( ( j & 1 ) == 1 ) cout << left;
else cout << right;
The original was:
if ( j % 2 == 0 ) cout << right;
else cout << left;
Regards herge
Quote from: herge on October 29, 2008, 10:44:51 PM
Hi All:
So the end result is:
if ( ( j & 1 ) == 1 ) cout << left;
else cout << right;
The original was:
if ( j % 2 == 0 ) cout << right;
else cout << left;
Regards herge
Hi herge, Im curious about the speed and the code size generated by C compared to asm.
Hi herge:
Wasn't there something on the daily wtf about this?
Hi Farabi:
10/30/2008 10:59 AM 874 fib.cpp
10/30/2008 10:59 AM 142,848 fib.exe
10/30/2008 10:59 AM 9,606 fib.obj
10/30/2008 10:59 AM 393,216 fib.tds
10/31/2008 03:18 AM 1,768 fib.asm
10/21/2008 03:55 PM 3,382 fib.exe
10/21/2008 03:55 PM 288,289 fib.obj
10/21/2008 03:55 PM 353,280 fib.pdb
Regards herge