HI
I've started a project called 32-bit Asm calculator!
Actually I'm going to implement sth like this:
http://www.manhunter.ru/releases/108_32_bit_asm_calculator_1_2.html
The aim is Only learning, I will share source and project details here from first steps,
Interested people can help to improve code or suggest change/add sth in the program.
At the end we will have a handy tool + a good source (I hope!)
first version:
not cool code, and many bugs!
did it just for start :)
Hi nightmare, welcome on board. Your calculator looks good.
Thanks hutch--,
I'm working on it, ATM I want improve and expand the code skeleton, then try adding new features.
So any idea about Switch Case part? or working with Radio Buttons? I have no idea what's best way to get a message from app when any of radio buttons gets changed, should I check all of them one by one?
Whenever a radio button is clicked, a WM_COMMAND message is sent to the app with the button identifier in the low-order word of the wParam parameter. Just process those mesages to keep track of which buttons are on/off. When it's time to perform the computation, you will then have the info available without having to check them one by one.
sure, I wrote the following lines to check if the message is from Radio buttons or not:
(idc_xor to idc_ror are radio buttons identifiers)
cmp ax,idc_xor
jb _skip
cmp ax,idc_ror
ja _skip
;....
_skip:
but when some one for example clicks on ROR radio button, to find out it's ROR we should check all one by one, since I will add more than 20 radio buttons it's not good way.
Did I get your way?
If your buttons are given sequential IDs from IDC_XOR to IDC_ROR, all you need to do is subtract IDC_XOR from the button ID you receive and then use this as the index into a table of function offsets. Then you can just call the function offset - you don't care which function it really is, it just takes parameters, performs its function, and returns the result.
Of course, to do this you must make sure that all of these function have the same form (e.g. take two parameters.)
A Table, I had this in mind too, but was looking for a decent solution. seems there are not many.
So will do it in this way!
regards.
Give them all the BS_AUTORADIOBUTTON style, group them together in your resource file and give the first one the additional WS_GROUP style.
When you initialize your dialog box, use CheckRadioButton to check whichever one you want and mark it as ON (all the others will be OFF). Keep track of which one is ON. When you get a message that one of them has been clicked, turn OFF the one previously ON, and turn ON the new one, updating which one is now ON. When it's time to compute, simply retrieve which is ON and act accordingly.
Quoteturn OFF the one previously ON, and turn ON the new one
The problem is how know which one is clicked?!
handle WM_COMMAND, BN_CLICKED
Quotehandle WM_COMMAND, BN_CLICKED
sure, but if you read above posts we are looking for a way to find clicked button without checking all radio buttons one by one (there are 32 radio buttons!)
Assuming your radio buttons have IDs from 501 to 532, and you set the 501 initially ON, and keep which button is ON in a variable such as butON,
when one of the radiobuttons is clicked, a WM_COMMAND message is sent with the notification code in the high word of the wParam and the button ID in the low word of wParam. The BN_CLICKED notification being 0, all you need to do is to check the wParam for one of the button IDs. If your radiobuttons are set up as I explained before, Windows takes care of repainting (turning ON or OFF) the buttons as required.
.if uMsg == WM_COMMAND
.if wParam >= 501 && wParam <= 532
push wParam
pop butON
.endif
When it's time to compute, retrieve the value in butON and proceed from there.
Ok, now I have ID of clicked radio button into butON.
In other hand I have 32 cases of code. (xor, and, etc)
Imagine AND radio is clicked, now how I realize it's AND radio button and jump to AND case of code?
As someone else seems to have suggested before, make a table of the offsets of your functions (FunctionTable) according to the same ordering as of your radiobutton IDs and, assuming all your functions take their parameters from global variables, fill those global variables and then:
mov eax,butON
sub eax 501
mov eax,FunctionTable[eax*4]
call eax
OK! I thought you have a solution for this this without table (according to your first post) so I did continue the discussion!
Thanks anyway :)
Ok, Here is new version (including source)
Waiting for suggestions/bugs report.
Thanks all.
mov eax,operand1
mov ecx,operand2
mov edx,operand_idc
jmp Table-4*IDC_XOR[edx*4]
case_01:
xor eax,ecx
jmp _endsw
case_02:
and eax,ecx
jmp _endsw
even smaller:
mov eax,operand1
mov ecx,operand2
mov edx,operand_idc
call Table-4*IDC_XOR[edx*4]
_endsw:
;
;
;
case_01:
xor eax,ecx
ret
case_02:
and eax,ecx
ret
you could also return a status in EDX for the ones like case_18
because the value in EDX is normally non-zero (it's the vector address), i would use EDX=0 to indicate an error
that way, you don't have to do anything to EDX for most of the operations
mov eax,operand1
mov ecx,operand2
mov edx,operand_idc
call Table-4*IDC_XOR[edx*4]
or edx,edx
jz op_error
_endsw:
Hi dedndave,
Thanks for your attention, but
Quotecase_01:
xor eax,ecx
ret
we are not in function, so RET will prevent execution of other lines.
Quotemov eax,operand1
mov ecx,operand2
some calls like EnableWindow overwrite eax and ecx, and it was better than push pop, but yes I should remove them from some of cases to make code smaller and faster.
yah - but you can fix that easy enough
it is just assembler symantics
case_01 PROC
xor eax,ecx
ret
case_01 ENDP
make a little PROC for each function
Dave, that's not really smaller when the stack-frame handling is automatically inserted (yes, we can turn that off, but then it's more junk than you're replacing.)
The jumps are fine.
there will be no prologue or epilogue generated if there are no "uses", parameters, or locals
if you disassemble this proc, you will see 2 instructions only
case_01 PROC
xor eax,ecx
ret
case_01 ENDP
If we use Proc NEAR I think it looks fine.
but for now I used same jumps (removed junk codes) maybe I change it in future.
here is updated one.
improved code, added some new features.
Next plan is adding Flags status to dialog!
Here is a simple example for using a table. Note the use of "global" LOCAL variables in the miniprocs.
include \masm32\include\masm32rt.inc
MyTest PROTO: DWORD, :DWORD
.code
AppName db "Masm32 is great!", 0
Hello db "What's your choice?", 0
start:
invoke MyTest, offset AppName, addr Hello
exit
MyTest proc arg1:DWORD, arg2
LOCAL lvYes, lvNo, lvCancel, locbuf[260]:BYTE
.data
TheTable dd L0, L1, L2
.code
mov lvYes, "seY"
mov lvNo, "oN"
mov lvCancel, "eyB"
MsgBox 0, arg1, arg2, MB_YESNOCANCEL
xor ecx, ecx ; default: 0
lea edi, locbuf
.if eax==IDYES
inc ecx
.elseif eax==IDNO
add ecx, 2
.endif
call TheTable[4*ecx]
MsgBox 0, edi, "Your choice", MB_OK
ret
L0:
mov eax, lvCancel
mov [edi], eax
retn
L1:
mov eax, lvYes
mov [edi], eax
retn
L2:
mov eax, lvNo
mov [edi], eax
retn
MyTest endp
end start
Sounds good, other friends noticed this method before as well.
Probably I switch to it when coding all features and fixing bugs finished.
ah yes - the explicit RETN avoids any epilogue generation
what you have works fine - stay with it - lol
i just mentioned it in passing
mainly, the repeated mov eax,operand1/mov ecx,operand2 instructions was what caught my eye :P
Quote from: dedndave on April 15, 2011, 05:40:24 PM
ah yes - the explicit RETN avoids any epilogue generation
Exactly, very handy. I have switched to this system because it allows to have multiple miniprocs that all can access the same set of local variables - great for a WndProc.
On a side note: The L0, L1, L2 lables are defined in global data but their scope is local. Not so obvious but I tested that with ml 6.15 and 9.0 and JWasm.
with older versions of masm, you could nest procedures
i miss that :P
New version.
Added some features and CPU Flags status to dialog.
Fixed some bugs.
(http://oi56.tinypic.com/2j26vzo.jpg)
hi,
bsf/bsr could be implemented implicit, by adding an status bar showing information about both operands.
Hi qWord,
Sorry but I couldn't get what exactly you mean.
hi,
look at the attachment
qWord
Thanks, nice implement and good idea.