Hello.

I'll be surprised if many of you remember the first time I logged in here at 13 years old, because now I'm 17 and still haven't learned much. That is not to say I'm not interested, but I kept running into walls and like most people my age, there is no shortage of other things that can occupy my interest.

Since my last posts I've moved almost entirely to Linux, with the help of WINE. I'm currently using the FASM compiler, which could undoubtedly be one of my issues when trying to learn assembly, since the vast majority of code is in other languages. Nonetheless, I've run into a problem and can't figure it out.

The below code gives me divide by zero errors every time, and yet just before the DIV instructions I've set up instructions to skip the DIV instruction if the divisor is zero. I've traced the code with Ollydbg and I still can't figure it out.

The programs is simply intended to count a number of CPU cycles using RTDSC and display the result in a messagebox. I've written a separate chunk of code to attempt to translate the binary result to ASCII so I can pass the string to the MessageBox function.

Please help? The compiled code is attached, source inline.

Thank you for your time.

; Template for program using standard Win32 headers

format PE GUI 4.0
entry start

include 'win32w.inc'


section '.text' code readable executable

  start:

        invoke  GetModuleHandle,0
        mov    ,eax
        invoke  LoadIcon,0,IDI_APPLICATION
        mov    ,eax
        invoke  LoadCursor,0,IDC_ARROW
        mov    ,eax
        invoke  RegisterClass,wc
        test    eax,eax
        jz      error

        invoke  CreateWindowEx,0,_class,_title,WS_VISIBLE+WS_DLGFRAME+WS_SYSMENU,128,128,800,192,NULL,NULL,,NULL
        test    eax,eax
        jz      error

  msg_loop:
        invoke  GetMessage,msg,NULL,0,0
        cmp    eax,1
        jb      error
        je      end_loop
        jg      msg_loop
        invoke  TranslateMessage,msg
        invoke  DispatchMessage,msg
        jmp    msg_loop

  error:
        ;invoke  PeekMessage,msg,NULL,0,0,0
        ;push    edi
        ;push    esi
        ;mov    edi, clcks
        ;mov    esi, msg
        ;movsd
        ;pop    esi
        ;pop    edi
        invoke  MessageBox,NULL,,NULL,MB_ICONERROR+MB_OK

  end_loop:
        invoke  ExitProcess,

proc WindowProc uses eax ebx edx ecx esi edi, hwnd,wmsg,wparam,lparam
        cmp    ,WM_DESTROY
        je      .wmdestroy
        jmp    .rdtsc                                                  ;Jump to my code
  .defwndproc:
        invoke  DefWindowProc,,,,
        jmp    .finish
  .wmdestroy:
        invoke  PostQuitMessage,0
        xor    eax,eax
  .finish:
        ret
        jmp    error

  .rdtsc:
        xor    eax,eax                                                      ;start of my code
        cpuid
        rdtsc
        mov    , eax
        cpuid
        rdtsc
        mov    , eax
        sub    eax,
        mov    , eax
  .Start:
        test    eax, eax                          ;Is it zero?
        jz      .Return                          ;If Zero, return (to avoid divide by zero errors)

        mov    eax, Base

  .Mainloop:
        cmp    , eax                    ;Is the result greater than 9?
        jge    .Carry                            ;If so, move the decimal

        mov    eax,

        div   
        add    eax, 30h                          ;Convert to ASCII

        mov    , eax              ;String this character
        add    , 4

        mov    eax, Base
        cmp    , eax                    ;Have we reached the ones-place yet?
        je      .Return                          ;If so, terminate.
        test    eax,eax
        jz      .Return
        mov    eax,
        div                              ;Raise decimal again
        mov    , eax
        jmp    .Mainloop

  .Carry:
        mov    eax,
        mul                              ;Decimal*Base=Decimal. Lower the decimal
        mov    , eax                    ;Reinstate the Decimal
        jmp    .Mainloop

  .Return:
        invoke  MessageBox,NULL,,_die,MB_OK+MB_ICONEXCLAMATION+MB_SYSTEMMODAL
        jmp    .defwndproc

endp


section '.data' data readable writeable

  _class TCHAR 'FASMWIN32',0
  _title TCHAR 'yeahyeahyeah',0
  _error TCHAR 'Startup failed.',0
  _die  TCHAR 'DIED!',0
  _bye  TCHAR 'bye',0

  clcks        dd      0
  Time1        dd      0
  Time2        dd      0
  Base = 10
  Basex        dd      10
  Decimal      dd      10
  Result        dd      4096
  String        rd      10
  StringPointer dd      String

  wc WNDCLASS 0,WindowProc,0,0,NULL,NULL,NULL,COLOR_BTNFACE+1,NULL,_class

  msg MSG


section '.idata' import data readable writeable

  library kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'

  include 'api\kernel32.inc'
  include 'api\user32.inc'     
Attachments:
Posted on 2011-05-26 20:48:50 by keantoken
'Scuse me for laughin'. Seems like everybody gets bit by this one! As soon as I read "divide by zero", I knew what the problem was.

This is neither a Windows issue nor a Fasm issue.The implicit operands to "div" (by 32-bits) are edx:eax / . Note the "edx"! If the result won't fit in eax, which it won't if edx >=10 (in this case), it causes an overflow exception. Instead of calling this a "divide overflow exception", it gets reported as "divide by zero", or sometimes "floating point error"(!). The solution is very simple: "xor edx, edx" (or "mov edx, 0") right before the "div". I'm not sure your conversion routine will work, but that should restore forward progress.

Hint: 1234 divided by ten gives eax=123, edx=4...

Best,
Frank

Posted on 2011-05-27 23:51:51 by fbkotler
Thanks!!

Okay, I did what you said. Although I should include edx in the calculations, I am going to simply truncate it until I can get the program to work.

I have another very odd problem.

At this instruction in .Carry:


       mov     , eax                  


It appears that AH and AL are getting swapped because when eax=1027, l=2710. Or when eax=3e8, .
Posted on 2011-05-28 17:13:22 by keantoken
This is a common misunderstanding when starting out with assembly.  On Intel chips the 'little-endian' memory layout is used.
That is, when moving from register to memory, the lower 16 bits of eax dword ( the little-end )  - eg: the word contained in AX ( the AH/AL part ) - are stored in lower memory while the upper bits is stored in higher memory.  It makes sense when you think about the higher bits stored higher in memory.
Of course, when you do a memory dump, you have to do a mental translation as us humans prefer the bigger parts of a number listed first ;)
Posted on 2011-05-28 18:57:15 by p1ranha
Finally, after doing this all day, I managed to get it to almost work.

I still haven't figured out how to load the ASCII characters into a string and then forward that string to the MessagBox title, but up to that part the ASCII encoder works. Now I'll work on making it use EDX as well so it will return the right number from RTDSC.

I'm discovering how difficult it may be to divide 64-bit numbers by 64-bit numbers...
Posted on 2011-05-29 06:04:23 by keantoken