переполнение eax при выполнении арифм.команд

Тема в разделе "WASM.BEGINNERS", создана пользователем biont, 20 ноя 2006.

  1. biont

    biont New Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2006
    Сообщения:
    2
    Добрый вечер, уважаемые кодеры.
    Написал программу, которая должна выполнять функцию цифрового метронома (прибор, способный производить произвольное количество тактовых долей времени на слух; служит как вспомогательный прибор для установления точного ритма в музыкальном произведении.) Алгоритм простой, но и тут умудрился наступить на грабли. При изменении ритма (значения перем. position) ползунком трекбар-контрола программа завершает свою работу. Посмотрел в olly, ошибка в переполнении eax при выполнении команд div и mul; я позволил себе не делать проверку на переполнение, поскольку результат в eax после выполнения команд умножения и деления не может превышать значения 240*100/3=8000 (если не прав, готов пройти экзекуцию ремнем и до конца дней своих читать книги по азму :). Еще одна проблема в вызове функции MessageBeep, она упорно не хочет работать. Пожалуйста, подскажите, как исправить ошибки. Thx.

    Код (Text):
    1. .386
    2. .model flat, stdcall
    3. option casemap:none
    4.  
    5. ;includes
    6. ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    7. include C:\masm32\include\windows.inc
    8. include C:\masm32\include\kernel32.inc
    9. include C:\masm32\include\user32.inc
    10. include C:\masm32\include\gdi32.inc
    11. include C:\masm32\include\comctl32.inc
    12.  
    13. includelib user32.lib
    14. includelib kernel32.lib
    15. includelib gdi32.lib
    16. includelib comctl32.lib
    17.  
    18.  
    19. .data
    20. ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    21. format_string   db  "%03i",0
    22. position    dd  120
    23. TimerValue  dd  1000
    24. status      dd  0
    25.  
    26. .data?
    27. ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    28. icex        INITCOMMONCONTROLSEX    <>
    29. buffer      db  4 dup (?)
    30.  
    31. .const
    32. ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    33. IDD_DLG1    equ  1000
    34. IDC_TRB1    equ  1001
    35. IDC_MIN     equ  1002
    36. IDC_MAX     equ  1003
    37. IDC_START   equ  1004
    38. IDC_STOP    equ  1005
    39. IDT_TIMER   equ  1
    40.  
    41. ;procedures prototypes
    42. DialogProc  proto :dword,:dword,:dword,:dword
    43. TimerInit   proto :dword
    44.  
    45. ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    46.  
    47. .code
    48. ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    49. start:
    50.  
    51. mov icex.dwSize,sizeof INITCOMMONCONTROLSEX
    52. mov     icex.dwICC,0FFFFh
    53. invoke  InitCommonControlsEx,addr icex
    54.  
    55. xor ebx,ebx
    56. invoke  GetModuleHandle,ebx
    57. invoke  DialogBoxParam,eax,IDD_DLG1,ebx,offset DialogProc,ebx
    58. invoke  ExitProcess,eax
    59.  
    60.  
    61. DialogProc proc uses ebx ecx edx esi edi hwin:dword, umsg:dword, wparam:dword, lparam:dword
    62. ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    63. local   hdc:HDC
    64. local   ps:PAINTSTRUCT
    65. local   rect:RECT
    66.  
    67. .if umsg == WM_INITDIALOG
    68.     invoke  SendDlgItemMessage,hwin,IDC_TRB1,TBM_SETRANGEMIN,FALSE,60
    69.     invoke  SendDlgItemMessage,hwin,IDC_TRB1,TBM_SETRANGEMAX,FALSE,240
    70.     invoke  SendDlgItemMessage,hwin,IDC_TRB1,TBM_SETPOS,TRUE,position
    71.     invoke  SetFocus,hwin
    72.     invoke  SetTimer,IDT_TIMER,NULL,TimerValue,NULL
    73.  
    74. .elseif umsg == WM_TIMER
    75.     .if status == 1
    76.     invoke  MessageBeep,-1
    77.     .endif
    78.  
    79. .elseif umsg == WM_HSCROLL
    80.     mov eax,wparam
    81.     and eax,0FFFFh  ; ???
    82.  
    83.         .if     eax == SB_THUMBPOSITION
    84.     mov eax,wparam
    85.     shr eax,16
    86.     mov position,eax
    87.     invoke  InvalidateRect,hwin,NULL,FALSE
    88.     invoke  TimerInit,hwin
    89.  
    90.         .elseif eax == SB_THUMBTRACK
    91.     mov eax,wparam
    92.     shr eax,16
    93.     mov position,eax
    94.     invoke  InvalidateRect,hwin,NULL,FALSE
    95.     invoke  TimerInit,hwin
    96.     .endif
    97.        
    98. .elseif umsg == WM_PAINT
    99.     invoke  wsprintf,offset buffer,offset format_string,position
    100.     add esp,12
    101.  
    102.     invoke  BeginPaint,hwin, addr ps
    103.     mov hdc,eax
    104.     invoke  TextOut,hdc,130,20,offset buffer,3
    105.     invoke  EndPaint,hwin,addr ps
    106.  
    107. .elseif umsg == WM_COMMAND
    108.     .if wparam == IDC_START
    109.     mov status,1
    110.     .elseif wparam == IDC_STOP
    111.     mov status,0
    112.     .endif
    113.  
    114. .elseif umsg == WM_CLOSE
    115.     invoke  EndDialog,hwin,0
    116.     invoke  KillTimer,hwin,IDT_TIMER
    117.    
    118. .endif
    119.  
    120. xor eax,eax
    121. ret
    122. DialogProc endp
    123.  
    124. TimerInit   PROC hwin:dword
    125. local   divis:dword
    126. local   multipl:dword
    127. mov divis,3
    128. mov multipl,50
    129.  
    130. pusha
    131. xor     eax, eax
    132. mov     eax, position   ; current TrackBar value
    133. div     divis       ; error - integer overflow!!!
    134. mul multipl     ; error - integer overflow!!!
    135. mov     TimerValue,eax  ;TimerValue = position / 60 * 1000 = position / 3 * 50
    136. invoke  KillTimer,hwin,IDT_TIMER
    137. invoke  SetTimer,IDT_TIMER,NULL,TimerValue,NULL
    138. popa
    139. ret
    140. TimerInit ENDP
    141.  
    142. ; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    143. end start
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Перед div нужно очищать регистр edx: xor edx,edx для беззнаковых eax или cdq для знаковых
     
  3. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Команда div принимает на входе 64-битовое значение edx:eax. Нужно обнулять edx (а не eax).
     
  4. biont

    biont New Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2006
    Сообщения:
    2
    виноват, надо было читать доку на div/mul, а потом уж вопросы задавать.
    invoke SetTimer,IDT_TIMER,NULL,TimerValue,NULL :/ исправил на
    invoke SetTimer,hwin,IDT_TIMER,TimerValue,NULL

    Большое спасибо!