News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Conversion issue

Started by boogara, September 30, 2007, 05:09:05 AM

Previous topic - Next topic

boogara

I'm using the latest version of MASM put out at www.movsd.com (I think the website is), as well as the SP2.  Now, I know SetTimer works in the code, because if I set the timer to a hard-coded value, it works fine...the problem occurs when trying to setup a timer based on user's input.

What happens is I had set up a timer to display a message box when the timer was finished (ie: set a timer for 1 second...and in second a message box would be displayed), but it's like the timer is set to 0 milliseconds.

I've been trying to fix this for a few hours...reading more on how MUL works (since that was originally the cause for posting this...but finding out now that entering any other desired value causes the same problem. [this will make sense once the code is shown])

First, the declarations:

.data

; How many milliseconds it takes for each type of break (used for SetTimer invoke)
WRAPUP dd 3600     ; 2 minutes
OF_BREAK dd 90000   ; 15 minutes
OH_BREAK dd 360000 ; 1 hour
TEST_BREAK dd 1000    ; Used for testing timer function

.data?

; Template code snipped-out
buffer db 512 dup(?)
timer dw 512 dup(?)
holder dw 512 dup(?)
yeaup dd 512 dup(?)


Here's the block of code that's causing the issues:


.if ax == IDC_START ; Was the "Start Timer" button clicked?
invoke GetDlgItemText, hWin, IDC_TIME, addr buffer, 512 ; Store the number entered into variable buffer
invoke FpuAtoFL, addr buffer, addr buffer, DEST_MEM ; Convert "buffer" (which is a string) to an integer, then save the value back into buffer

.if eax == 0 ; An error occured while trying to convert...so lets do it
invoke MessageBox, hWin, addr FailedAtoL, addr AppName, MB_OK
.else ; Everything went fine...so lets get with the actual work
invoke FpuTrunc,addr buffer,addr buffer,SRC1_REAL

.if buffer==2
invoke SetTimer,hWin,1,WRAPUP,NULL
.elseif buffer==15
invoke SetTimer,hWin,1,OF_BREAK,NULL
.elseif buffer==60
invoke SetTimer,hWin,1,OH_BREAK,NULL
.else
; Clear all needed registers first
mov ax, 0
mov bx, 0
mov dx, 0

mov al, buffer ; Store the buffer (minutes to wait) amount in AX
mov bh, 60 ; Store 60 into BH (60 = seconds in minutes)
mov bl, 100 ; Store part of millisecond count into BL
mul bh ; Multiply AX by 60
mul bl ; Multiply AX by 100
mov bh, 0 ; Now complete the millisecond process
mov bh, 10 ; by emptying BH and storing 10 in it
mul bh ; Now multiply AX by 10
shl eax, 16 ; Shift DX:AX until
shrd eax, edx, 16 ; EAX itself contains the solution
mov yeaup, edx ; Store the result into yeaup

invoke SetTimer,hWin,1, yeaup,NULL
.endif
.endif
.endif


I know it looks a lil' over-complicated with the multiple mov/mul's...but, right now I'm gunning for workability...optimization will come later.

I've included the FPU library and header...and it compiles fine (finally), but just the timer seems to be a lil' screwy.  I've also done a check on the yeaup variable (converting it back to ASCII with the FpuFLtoA call), which displays a "0" (w/o quotes) in a message box...so, perhaps it's not getting the edit box text correctly?

Side note: This isn't a school project...or anything of that sort...I just got the idea one time while at work to write a program that will let me know when breaks and the such are over with.  Also...I know this can be done in C/C++ (and much easier), but...eh, I have it working almost to pefection...and I know I can just hard-code everything but the inputted value, but right now it's just a "hm...lets get this to work this way" phase for me right now.

sinsi

one millisecond = 1/1000th of a second...so

  2 minutes = 120,000 ms (2*60*1000)
15 minutes = 900,000 ms (15*60*1000)
1 hour = 3,600,000 ms (60*60*1000)
Light travels faster than sound, that's why some people seem bright until you hear them.

boogara

Quote from: sinsi on September 30, 2007, 06:25:34 AM
one millisecond = 1/1000th of a second...so

  2 minutes = 120,000 ms (2*60*1000)
15 minutes = 900,000 ms (15*60*1000)
1 hour = 3,600,000 ms (60*60*1000)

Thanks ^_^  Had a feeling the math was wrong...but, still baffled as to why my program isn't working as expected.

(Really thinking FPU won't give me want I want...but it's the only thing I can find that will convert a string to an integer (or in this case, float))

Mark Jones

Instead of FpuAtoFL, you could try AtoDW (ASCII to DWORD.) Here's an example how it is used:


; get timing interval value from user
    invoke GetDlgItemText,hWnd,IDC_EDT1,addr szTime,5
    invoke atodw,addr szTime
    mov [dwTime],eax
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

boogara

Quote from: Mark Jones on September 30, 2007, 09:13:09 PM
Instead of FpuAtoFL, you could try AtoDW (ASCII to DWORD.) Here's an example how it is used:


; get timing interval value from user
    invoke GetDlgItemText,hWnd,IDC_EDT1,addr szTime,5
    invoke atodw,addr szTime
    mov [dwTime],eax

Thanks :)  I'll look into it, especially if the below code doesn't shape up...but, I think I found a better(?) way to get an int from a dialog box (couldn't figure out how to really work it before, thus why I used the FPU* calls)...


buffer dd ?
dead   db 1024 dup(?)

invoke GetDlgItemInt,hWin,IDC_TIME,0,0 ; Get the time (in minutes) for the break, and convert it to an integer

mov buffer, eax ; Store the value of IDC_TIME into buffer

xor ebx, ebx ; Make sure the EBX register is empty

; While we still have seconds left in the buffer...
.while buffer > 0
add ebx, 1000 ; Add 1000 (one thousand) to the value in EBX
dec buffer       ; We took care of a second, so now we decrement the buffer by one
.endw

mov buffer, ebx ; Move the result of EBX into buffer

; Below two lines used for debugging the above while() and mov code
invoke crt__itoa,buffer,addr dead,10
invoke MessageBox,hWin,addr dead,addr AppName,MB_OK

invoke SetTimer,hWin,1, buffer,NULL ; Create a timer for our new value


Works for the most part...still getting some troubles (the messagebox doesn't popup when you enter like "60" for the time [which is weird, because it seems to not work at only 60...59, 61, etc...works, just not 60)...but, I'm getting closer.

Edit: Haha...looked over my code again, and realized why "60" wouldn't work...it's because I already had "60" defined above, so thus it'd never reach...XD;

raymond

A few comments in case you may want to use some of the instructions in future projects.

Quoteinvoke FpuTrunc,addr buffer,addr buffer,SRC1_REAL

Without any destination flag in the uID, the default returns a REAL10 at the memory address specified as the lpDest parameter.

If DEST_IMEM had been OR'ed as the destination flag, a 32-bit binary integer would have been returned at the specified address. However, you were later trying to access the buffer as if it contained only one byte of data. If the returned value had been larger than 255, you would have checked only part of it.

Quotemul bh      ; Multiply AX by 60
mul bl      ; Multiply AX by 100

When you use the mnemonic mul with a byte as the operand, you effectively multiply the content of the AL register and the result is returned in the AX register. Assuming that bh would contain 5, the result in AX would be 300, with 44 in AL and 256 in AH. Then, multiplying the 44 in AL by BL (i.e. 100), the 4400 result would see 48 in AL and 4352 in AH. Multiplying 48 later by BH which contained 10, the final result would have been 480 in AX instead of your expected 5x60x100x10=300000.

Raymond
When you assume something, you risk being wrong half the time
http://www.ray.masmcode.com