Author Topic: Question about WinApi1.o2bas  (Read 261 times)

0 Members and 1 Guest are viewing this topic.

Arnold

  • Sr. Member
  • ****
  • Posts: 469
Question about WinApi1.o2bas
« on: November 09, 2017, 04:28:46 PM »
Hi Charles,

hopefully you do not think I am unbalanced, jumping from topic to topic. But this is something which is on my 'must know' list since I started to learn Oxygenbasic.

I am able to run \examples\Asm32\WinApi1.o2bas if I comment out the #asm statement. I can also compile to an exe file which depends on Oxygen.dll. But I cannot create an independent executable using RTL32.inc. I assume there are statements in WinApi.o2bas which conflict with RTL32.inc. Which modifications are needed in WinApi1.o2bas to create an independent exe file using as many assembler instructions as possible?

There is an intention with this question. I always wanted to realize some of the existing asm tutorials using Oxygenbasic but I do not really know where to start. It would be interesting to see how much Basic is in fact necessary to create WinApi1.exe and to what extent assembly can be used.

Roland

Arnold

  • Sr. Member
  • ****
  • Posts: 469
Re: Question about WinApi1.o2bas
« Reply #1 on: November 11, 2017, 06:50:12 AM »
This is what I mean:

I took Iczelion tutorial no.3 line by line and searched for what would make sense to do in assembly. But I always ended in Basic. I think it does not make sense to use assembly statements for things which Oxygenbasic already does for me and which I cannot do better.

So probably for WinMain, the wndproc callbacks and Windows functions there will be no need for extra assembly. But in case of user functions and subs when would it be advantageous to use assembler?

Roland

Code: OxygenBasic
  1. '.386
  2. '.model flat,stdcall
  3. 'option casemap:none
  4. 'include \masm32\include\windows.inc
  5. 'include \masm32\include\user32.inc
  6. 'include \masm32\include\kernel32.inc
  7. 'includelib \masm32\lib\user32.lib
  8. 'includelib \masm32\lib\kernel32.lib
  9.  
  10. #compact
  11.  
  12. $ filename "Win.exe"
  13. 'include "$inc/RTL32.inc"
  14. include "$inc/minwin.inc"
  15.  
  16. % COLOR_WINDOW=5
  17.  
  18. 'WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
  19. declare sub WinMain(sys hInst,hPrevInst, asciiz* CmdLine, sys CmdShow)
  20.  
  21. '.data
  22. 'ClassName db "SimpleWinClass",0
  23. 'AppName  db "Our First Window",0
  24. zstring ClassName="SimpleWinClass"
  25. zstring AppName="Our First Window"
  26.  
  27. '.data?
  28. 'hInstance dd ?
  29. 'CommandLine dd ?
  30. sys hInstance
  31. asciiz ptr CommandLine
  32.  
  33. '.code
  34. 'start:
  35. '    invoke GetModuleHandle, NULL
  36. '    mov    hInstance,eax
  37. hInstance=GetModuleHandle NULL
  38. '    invoke GetCommandLine
  39. '    mov    CommandLine,eax
  40. &CommandLine=GetCommandLine
  41. '    invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
  42. WinMain hInstance, NULL, CommandLine, SW_SHOWDEFAULT
  43. '    invoke ExitProcess, eax
  44.  
  45. 'WinMain proc hInst:HINSTANCE, hPrevInst:HINSTANCE, CmdLine:LPSTR, CmdShow:DWORD
  46. sub WinMain(sys hInst,hPrevInst, asciiz* CmdLine, sys CmdShow)
  47. '    LOCAL wc:WNDCLASSEX
  48. '    LOCAL msg:MSG
  49. '    LOCAL hwnd:HWND
  50.    WNDCLASSEX wc
  51.     MSG msg
  52.     sys hwnd
  53.    
  54. '    mov   wc.cbSize, SIZEOF WNDCLASSEX
  55.    wc.cbSize=SIZEOF WNDCLASSEX
  56. '    mov   wc.style, CS_HREDRAW or CS_VREDRAW
  57.    wc.style=CS_HREDRAW or CS_VREDRAW
  58. '    mov   wc.lpfnWndProc, OFFSET WndProc
  59.    wc.lpfnWndProc= @ WndProc
  60. '    mov   wc.cbClsExtra, NULL
  61.    wc.cbClsExtra= NULL
  62. '    mov   wc.cbWndExtra, NULL
  63.    wc.cbWndExtra= NULL
  64. '    push  hInstance
  65. '    pop   wc.hInstance
  66.    wc.hInstance=hInstance
  67. '    mov   wc.hbrBackground, COLOR_WINDOW+1
  68.    wc.hbrBackground= COLOR_WINDOW+1
  69. '    mov   wc.lpszMenuName, NULL
  70.    wc.lpszMenuName= NULL
  71. '    mov   wc.lpszClassName, OFFSET ClassName
  72.    wc.lpszClassName= @ ClassName
  73. '    invoke LoadIcon, NULL, IDI_APPLICATION
  74. '    mov   wc.hIcon, eax
  75.    wc.hIcon= LoadIcon NULL, IDI_APPLICATION
  76. '    mov   wc.hIconSm, eax
  77.    wc.hIconSm= LoadIcon NULL, IDI_APPLICATION
  78. '    invoke LoadCursor, NULL, IDC_ARROW
  79. '    mov   wc.hCursor, eax
  80.    wc.hCursor= LoadCursor NULL, IDC_ARROW
  81.  
  82.  
  83. '    invoke RegisterClassEx, addr wc
  84.    if not RegisterClassEx @ wc then mbox "Registration failed" : end
  85.    
  86. '    INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
  87. '           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
  88. '           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
  89. '           hInst,NULL
  90. '    mov   hwnd, eax
  91.    hwnd= CreateWindowEx NULL,@ ClassName,@ AppName,
  92.            WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
  93.            CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,
  94.            hInst,NULL
  95.     if hwnd=NULL then mbox "CreateWindow failed" : end      
  96.            
  97. '    invoke ShowWindow, hwnd, SW_SHOWNORMAL
  98.    ShowWindow hwnd, SW_SHOWNORMAL
  99. '    invoke UpdateWindow, hwnd
  100.    UpdateWindow hwnd
  101.    
  102. '   .WHILE TRUE
  103. '        invoke GetMessage, ADDR msg, NULL, 0, 0
  104. '        .BREAK .IF (!eax)
  105. '        invoke TranslateMessage, ADDR msg
  106. '        invoke DispatchMessage, ADDR msg
  107. '    .ENDW
  108.    while GetMessage @ msg, NULL, 0, 0
  109.         TranslateMessage @ msg
  110.         DispatchMessage @ msg
  111.     wend
  112.  
  113. '    mov     eax,msg.wParam
  114. '    ret
  115. 'WinMain endp
  116. end sub
  117.  
  118. 'WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
  119. function WndProc (sys hWnd, uint uMsg, sys wParam, lParam) as sys callback
  120. '    .if uMsg==WM_DESTROY
  121.    if uMsg=WM_DESTROY then
  122. '        invoke PostQuitMessage, NULL
  123.        PostQuitMessage NULL
  124. '    .else
  125.    else
  126. '        invoke DefWindowProc, hWnd, uMsg, wParam, lParam        
  127. '        ret
  128.        return DefWindowProc hWnd, uMsg, wParam, lParam
  129. '    .endif
  130.    endif
  131. '    xor eax,eax
  132. '    ret
  133. 'WndProc endp
  134. end function
  135.  
  136. 'end start
  137.  

Arnold

  • Sr. Member
  • ****
  • Posts: 469
Re: Question about WinApi1.o2bas
« Reply #2 on: November 11, 2017, 12:02:57 PM »
This is strange. I did not touch the tutorials since some time, because I did not understand much. And now it seems not to be so difficult.
In the code of Iczelion tutorial 5 I applied the first time the assembler statements of macro RGB and SelectObject which selects the handle of the logical font after CreateFont. The program works as expected, but is this really ok what I am doing?

Code: OxygenBasic
  1. '.386
  2. '.model flat,stdcall
  3. 'option casemap:none
  4.  
  5. #compact
  6.  
  7. $ filename "Text.exe"
  8. 'include "$inc/RTL32.inc"
  9. include "$inc/minwin.inc"
  10.  
  11. % COLOR_WINDOW=5
  12. % OUT_DEFAULT_PRECIS=0
  13. % OEM_CHARSET=255
  14.  
  15. 'WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
  16. declare sub WinMain(sys hInst,hPrevInst, asciiz* CmdLine, sys CmdShow)
  17.  
  18. 'include \masm32\include\windows.inc
  19. 'include \masm32\include\user32.inc
  20. 'include \masm32\include\kernel32.inc
  21. 'include \masm32\include\gdi32.inc
  22. 'includelib \masm32\lib\user32.lib
  23. 'includelib \masm32\lib\kernel32.lib
  24. 'includelib \masm32\lib\gdi32.lib
  25.  
  26. macro RGB (red,green,blue)
  27.         xor eax,eax
  28.         mov ah,blue
  29.         shl eax,8
  30.         mov ah,green
  31.         mov al,red
  32. end macro
  33.  
  34. '.data
  35. 'ClassName db "SimpleWinClass",0
  36. 'AppName  db "Our First Window",0
  37. 'TestString  db "Win32 assembly is great and easy!",0
  38. 'FontName db "script",0
  39. zstring ClassName = "SimpleWinClass"
  40. zstring AppName  = "Our First Window"
  41. zstring TestString  = "Win32 assembly is great and easy!"
  42. zstring FontName = "script"
  43.  
  44. '.data?
  45. 'hInstance HINSTANCE ?
  46. 'CommandLine LPSTR ?
  47. sys hInstance
  48. asciiz ptr CommandLine
  49.  
  50. '.code
  51. 'start:
  52. '    invoke GetModuleHandle, NULL
  53. '    mov    hInstance,eax
  54. '    invoke GetCommandLine
  55. '    mov CommandLine,eax
  56. '    invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
  57. '    invoke ExitProcess,eax
  58. hInstance=GetModuleHandle NULL
  59. &CommandLine=GetCommandLine
  60. WinMain hInstance, NULL, CommandLine, SW_SHOWDEFAULT
  61.  
  62. 'WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
  63. sub WinMain(sys hInst,hPrevInst, asciiz* CmdLine, sys CmdShow)
  64. '    LOCAL wc:WNDCLASSEX
  65. '    LOCAL msg:MSG
  66. '    LOCAL hwnd:HWND
  67.    WNDCLASSEX wc
  68.     MSG msg
  69.     sys hwnd
  70.  
  71. '    mov   wc.cbSize,SIZEOF WNDCLASSEX
  72. '    mov   wc.style, CS_HREDRAW or CS_VREDRAW
  73. '    mov   wc.lpfnWndProc, OFFSET WndProc
  74. '    mov   wc.cbClsExtra,NULL
  75. '    mov   wc.cbWndExtra,NULL
  76. '    push  hInst
  77. '    pop   wc.hInstance
  78. '    mov   wc.hbrBackground,COLOR_WINDOW+1
  79. '    mov   wc.lpszMenuName,NULL
  80. '    mov   wc.lpszClassName,OFFSET ClassName
  81. '    invoke LoadIcon,NULL,IDI_APPLICATION
  82. '    mov   wc.hIcon,eax
  83. '    mov   wc.hIconSm,eax
  84. '    invoke LoadCursor,NULL,IDC_ARROW
  85. '    mov   wc.hCursor,eax
  86.    wc.cbSize=SIZEOF WNDCLASSEX
  87.     wc.style=CS_HREDRAW or CS_VREDRAW
  88.     wc.lpfnWndProc= @WndProc
  89.     wc.cbClsExtra= NULL
  90.     wc.cbWndExtra= NULL
  91.     wc.hInstance=hInstance
  92.     wc.hbrBackground= COLOR_WINDOW+1
  93.     wc.lpszMenuName= NULL
  94.     wc.lpszClassName= @ClassName
  95.     wc.hIcon= LoadIcon NULL, IDI_APPLICATION
  96.     wc.hIconSm= LoadIcon NULL, IDI_APPLICATION
  97.     wc.hCursor= LoadCursor NULL, IDC_ARROW
  98.  
  99. '    invoke RegisterClassEx, addr wc
  100.    if not RegisterClassEx @wc then mbox "Registration failed" : end
  101.    
  102. '    INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
  103. '           WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
  104. '           CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
  105. '           hInst,NULL
  106. '    mov   hwnd,eax
  107. '    INVOKE ShowWindow, hwnd,SW_SHOWNORMAL
  108. '    INVOKE UpdateWindow, hwnd
  109.    hwnd= CreateWindowEx NULL,@ClassName,@AppName,
  110.            WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
  111.            CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,
  112.            hInst,NULL
  113.     if hwnd=NULL then mbox "CreateWindow failed" : end      
  114.  
  115.     ShowWindow hwnd, SW_SHOWNORMAL
  116.     UpdateWindow hwnd
  117.  
  118. '    .WHILE TRUE
  119. '                INVOKE GetMessage, ADDR msg,NULL,0,0
  120. '                .BREAK .IF (!eax)
  121. '                INVOKE TranslateMessage, ADDR msg
  122. '                INVOKE DispatchMessage, ADDR msg
  123. '    .ENDW
  124. '    mov     eax,msg.wParam
  125. '    ret
  126.    while GetMessage @msg, NULL, 0, 0
  127.         TranslateMessage @msg
  128.         DispatchMessage @msg
  129.     wend    
  130. 'WinMain endp
  131. end sub
  132.  
  133. 'WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
  134. function WndProc (sys hWnd, uint uMsg, sys wParam, lParam) as sys callback
  135. '    LOCAL hdc:HDC
  136. '    LOCAL ps:PAINTSTRUCT
  137. '    LOCAL hfont:HFONT
  138.    sys hdc
  139.     PAINTSTRUCT ps
  140.     sys hfont
  141.  
  142. '    .IF uMsg==WM_DESTROY
  143. '        invoke PostQuitMessage,NULL
  144. '    .ELSEIF uMsg==WM_PAINT
  145. '        invoke BeginPaint,hWnd, ADDR ps
  146. '        mov    hdc,eax
  147. '        invoke CreateFont,24,16,0,0,400,0,0,0,OEM_CHARSET,\
  148. '                            OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,\
  149. '                            DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,\
  150. '                            ADDR FontName
  151. '        invoke SelectObject, hdc, eax
  152. '        mov    hfont,eax
  153. '        RGB    200,200,50
  154. '        invoke SetTextColor,hdc,eax
  155. '        RGB    0,0,255
  156. '        invoke SetBkColor,hdc,eax
  157. '        invoke TextOut,hdc,0,0,ADDR TestString,SIZEOF TestString
  158. '        invoke SelectObject,hdc, hfont
  159. '        invoke EndPaint,hWnd, ADDR ps
  160. '        .ELSE
  161. '        invoke DefWindowProc,hWnd,uMsg,wParam,lParam
  162. '        ret
  163. '    .ENDIF
  164. '    xor    eax,eax
  165. '    ret
  166.    IF uMsg=WM_DESTROY then
  167.         PostQuitMessage NULL
  168.     ELSEIF uMsg=WM_PAINT then
  169.         hdc=BeginPaint hWnd, @ps
  170.         CreateFont 24,16,0,0,400,0,0,0,OEM_CHARSET,
  171.                             OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
  172.                             DEFAULT_QUALITY,DEFAULT_PITCH or FF_SCRIPT,
  173.                             @FontName
  174.         SelectObject hdc, eax
  175.         mov    hfont,eax
  176.        
  177.         RGB    200,200,50
  178.         SetTextColor hdc,eax
  179.         RGB    0,0,255
  180.         SetBkColor hdc,eax
  181.         TextOut hdc,0,0,@TestString,len TestString
  182.         SelectObject hdc, hfont
  183.         EndPaint hWnd, @ps
  184.     ELSE
  185.         return DefWindowProc hWnd,uMsg,wParam,lParam
  186.     ENDIF
  187.  
  188. 'WndProc endp
  189. end function
  190.  
  191. 'end start
  192.  

Arnold

  • Sr. Member
  • ****
  • Posts: 469
Re: Question about WinApi1.o2bas
« Reply #3 on: November 12, 2017, 03:41:39 PM »
The more I deal with the Iczelion tutorials the more I am surprised that I had so many trouble the first time. In the meantime I arrived at tutorial 11-2.
Most of the tutorials need a resource file and this one will need to be linked with a resource file too. I used the version of Oxygenbasic of June 2017, provided at GitHub.
Although I did not use many assembly statements (it would not make sense to me) everything of the original tut11-2 can be found in the code.
If I did everything right then it seems to me that OxygenBasic is not only a powerful JIT compiler but can also handle inline assembly without problems.

Roland

Code: OxygenBasic
  1. 'http://win32assembly.programminghorizon.com/tutorials.html
  2. 'tut11-02
  3.  
  4. 'Must be compiled as exe file, using a resource file
  5. 'can be done with MakeDialog.bat
  6.  
  7. #compact
  8.  
  9. $ filename "Dialog.exe"
  10. include "$inc/RTL32.inc"
  11. include "$inc/minwin.inc"
  12.  
  13. % COLOR_WINDOW=5
  14.  
  15. ' Additonal WinApi Functions
  16. ! GetDlgItem lib "user32.dll" alias "GetDlgItem" (sys hDlg, nIDDlgItem) as sys
  17. ! SetDlgItemText lib "user32.dll" alias"SetDlgItemTextA" (sys hDlg, int nIDDlgItem, char lpString) as bool
  18.  
  19. declare sub WinMain(sys hInst,hPrevInst, asciiz* CmdLine, sys CmdShow)
  20. declare function DlgProc (sys hWnd, uint uMsg, sys wParam, lParam) as sys callback
  21.  
  22. zstring ClassName = "SimpleWinClass"
  23. zstring AppName  = "Our Main Window"
  24. zstring MenuName = "FirstMenu"
  25. zstring DlgName = "MyDialog"
  26. zstring TestString = "Hello, everybody"
  27.  
  28. sys hInstance
  29. asciiz ptr CommandLine
  30.  
  31. % IDM_EXIT = 1
  32. % IDM_ABOUT = 2
  33. % IDC_EDIT  = 3000
  34. % IDC_BUTTON = 3001
  35. % IDC_EXIT = 3002
  36.  
  37. hInstance=GetModuleHandle NULL
  38. &CommandLine=GetCommandLine
  39. WinMain hInstance, NULL, CommandLine, SW_SHOWDEFAULT
  40.  
  41. sub WinMain(sys hInst,hPrevInst, asciiz* CmdLine, sys CmdShow)
  42.     WNDCLASSEX wc
  43.     MSG msg
  44.     sys hwnd
  45.  
  46.     wc.cbSize=SIZEOF WNDCLASSEX
  47.     wc.style= CS_HREDRAW or CS_VREDRAW
  48.     wc.lpfnWndProc= @WndProc
  49.     wc.cbClsExtra=NULL
  50.     wc.cbWndExtra=NULL
  51.     wc.hInstance=hInst
  52.     wc.hbrBackground=COLOR_WINDOW+1
  53.     wc.lpszMenuName= @MenuName
  54.     wc.lpszClassName= @ClassName    
  55.     wc.hIcon=LoadIcon NULL,IDI_APPLICATION
  56.     wc.hIconSm=LoadIcon NULL,IDI_APPLICATION    
  57.     wc.hCursor=LoadCursor NULL,IDC_ARROW
  58.  
  59.     if not RegisterClassEx @wc then mbox "Registration failed" : end
  60.  
  61.     hwnd= CreateWindowEx WS_EX_CLIENTEDGE,@ClassName,@AppName,
  62.            WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
  63.            CW_USEDEFAULT,300,200,NULL,NULL,
  64.            hInst,NULL
  65.     if hwnd=NULL then mbox "CreateWindowEx failed" : end      
  66.  
  67.     ShowWindow hwnd, SW_SHOWNORMAL
  68.     UpdateWindow hwnd
  69.  
  70.     while GetMessage @msg, NULL, 0, 0
  71.          TranslateMessage @msg
  72.          DispatchMessage @msg
  73.     wend        
  74. end sub
  75.  
  76. function WndProc (sys hWnd, uint uMsg, sys wParam, lParam) as sys callback
  77.     IF uMsg=WM_DESTROY then
  78.         PostQuitMessage NULL
  79.     ELSEIF uMsg=WM_COMMAND then
  80.         mov eax,wParam
  81.         if ax=IDM_ABOUT then
  82.             DialogBoxParam hInstance, @DlgName,hWnd, @DlgProc,NULL
  83.         else
  84.             DestroyWindow hWnd
  85.         endif
  86.     ELSE
  87.         return DefWindowProc hWnd,uMsg,wParam,lParam
  88.     ENDIF
  89. end function
  90.  
  91. function DlgProc (sys hWnd, uint iMsg, sys wParam, lParam) as sys callback
  92.     if iMsg=WM_INITDIALOG then
  93.         GetDlgItem hWnd,IDC_EDIT
  94.         SetFocus eax
  95.     elseif iMsg=WM_CLOSE then
  96.         EndDialog hWnd,NULL
  97.     elseif iMsg=WM_COMMAND then
  98.         mov eax,wParam
  99.         mov edx,eax
  100.         shr edx,16
  101.         if dx=BN_CLICKED then
  102.             mov eax,wParam  'otherwise will not work
  103.            if eax=IDC_EXIT then
  104.                 SendMessage hWnd,WM_CLOSE,NULL,NULL
  105.             elseif eax=IDC_BUTTON then
  106.                 SetDlgItemText hWnd,IDC_EDIT, @TestString
  107.             endif
  108.         endif
  109.     else
  110.         return FALSE
  111.     endif
  112.     return TRUE
  113. end function
  114.  

Charles Pegge

  • Author
  • *****
  • Posts: 3290
    • Oxygen Basic
Re: Question about WinApi1.o2bas
« Reply #4 on: November 13, 2017, 11:08:08 AM »
Hi Roland,

There was a clash between RTL32.inc and the bind statements in asm32\Winapi1.o2bas. I am testing out a solution but you can replace the bind statements entirely with extern lib declarations, or simply include MinWin.inc after RTL32.inc. It saves a lot of house-keeping.

This code originates from the very early formative time of OxygenBasic (July 2008!). Here is a modernised version using RTL32 and MinWin:

Code: [Select]
' Windows Hello World
' #2
' with winmain message loop and wndproc
' 12 July 2008
' 11:30 13/11/2017

' Charles Pegge


%    filename "t.exe"
uses rtl32
uses minwin

  var 4 cmdline,inst

  cmdline=GetCommandLine
  inst=GetModuleHandle 0
  call WinMain inst,0,cmdline,SW_NORMAL
  end
   

  o2 !10 ' align 16 bytes   
 
 
  '-------
  WinMain:
  '------- 
                    '
 

  push ebp
  mov ebp,esp
  'allocate stack space
  sub esp,100
  ' setup class data
  mov edi,esp
                     '
  def wclass     edi
  def style      [edi]
  def pWndproc   [edi+4]
  def cbClsExtra [edi+08]
  def cbWndExtra [edi+12]
  def hInstance  [edi+16]
  def icon       [edi+20]
  def cursor     [edi+24]
  def background [edi+28]
  def MenuName   [edi+32]
  def ClassName  [edi+36]
 
  ' window handle 
  def hWnd [edi+40]
   
  mov eax,CS_HREDRAW          '
  or  eax,CS_VREDRAW          '
  mov style,eax

  call fwd here : .here : pop eax : sub eax,here : add eax,WndProc
  mov pWndProc,eax

  mov  cbClsExtra,0   
  mov  cbWndExtra,0   
  mov  eax,[ebp+8]
  mov  hInstance,eax
  icon=LoadIcon 0, IDI_APPLICATION
  cursor=LoadCursor 0,IDC_ARROW
  background=GetStockObject WHITE_BRUSH '
  mov MenuName,0
  "HelloWin"
    mov ClassName,eax
    RegisterClass wclass
   
    (                           '
      cmp eax,0 : jnz exit                 '
      MessageBox 0,"Registration failed","Problem",MB_ICONERROR       '
      xor eax,eax              ' zero eax
      jmp long end_app         ' jmp xitwm
    )                          '


    hWnd=CreateWindowEx 0, ClassName,"Hello Window",
      WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT,CW_USEDEFAULT,640,480,
      0,0,hInstance,0
     
    (
      cmp eax,0 : jnz exit
      MessageBox 0,"Unable to create window","problem",MB_ICONERROR
      xor eax,eax             ' zero eax
      jmp long end_app          ' jmp xitwm
    )                           '
    ShowWindow hWnd,[ebp+20] ' show
    UpdateWindow hWnd


    '     MESSAGE LOOP          '
   
    add edi,40 ' place for wmsg struc
    (
      GetMessage edi,0,0,0        '
      cmp eax,0 : jz exit
      TranslateMessage edi
      DispatchMessage edi
      repeat
    )                      '
    mov eax,[edi+8]            ' Msg.wParam 3rd param
   
    end_app:
    ' deallocate stack space
    mov esp,ebp : pop ebp                 '
    ret 16
    ' end of WinMain


    type RECT
    (
    ' 16 bytes
    4  left
    4  top
    4  right
    4  bottom
    )

    type PAINTSTRUCT
    (
    ' 64 bytes
    4    hDC
    4    fErase
    rect rcPaint
    4    fRestore
    4    fIncUpdate
    32   rgbReserved
    )

    '-------   
    WndProc:
    '-------
    def hWnd   [ebp+08]
    def wMsg   [ebp+12]            '
    def wParam [ebp+16]            '
    def lParam [ebp+20]            '

    def WM_CREATE  1
    def WM_DESTROY 2
    def WM_PAINT   15
    def WM_CLOSE   16
    def WM_KEYDOWN 256
 
    push ebp : mov ebp,esp
    push ebx : push esi
    '
    'call _mem 'sets ebx address of bssdata
    addr ebx,bssdata
    '
    ' not using stack locals so no subractions for esp
   
            '
    mov eax,wMsg
    (
      (
        cmp eax, WM_CREATE : jnz exit
        xor eax,eax
        jmp long endselect
      )  ' end create
       
      (
        cmp eax, WM_DESTROY : jnz exit
        PostQuitMessage 0
        xor eax,eax
        jmp long endselect
      ) ' end destroy

      (
        cmp eax,WM_PAINT : jnz exit
        sub esp,100 ' extra workspace
        def cRect   [ebp-60]
        def hDC     [ebp-20]
        def Paintst  [ebp-100]
        '
        BeginPaint hWnd, @Paintst
        mov hDC,eax
        GetClientRect  hWnd, @cRect
          ' style
          ' 0x20 DT_SINGLELINE
          ' 0x04 DT_VCENTER
          ' 0x01 DT_CENTER
          ' 0x25
        DrawText hDC,"Hello World!",-1,@cRect,0x25
        EndPaint hWnd,@Paintst
        xor eax,eax
        jmp long endselect
      ) ' end paint
      (
        cmp eax,WM_KEYDOWN : jnz exit
        (
          mov eax,wParam
          cmp al,27 : jnz exit ' esc key
          PostMessage hWnd,WM_CLOSE,0,0
        )
        xor eax,eax  ' zero
        jmp long endselect
      ) ' end keydown
      ' case else
      DefWindowProc hWnd,wMsg,wParam,lParam
    ) ' end select
    endselect:
    '
    pop esi : pop ebx
    mov esp,ebp : pop ebp
    ret 16

The main problems with using Assembler as an alternative to Basic is 32bit/64bit compatability, and language granularity. OxygenBasic supports a form of structured Asm programming but most Assemblers require jumps to be done with labels (the original goto spaghetti programming :) )

You can make most lines of Basic reveal the underlying Asm by prefixing with #show. This is my main compiler debugging tool.

Arnold

  • Sr. Member
  • ****
  • Posts: 469
Re: Question about WinApi1.o2bas
« Reply #5 on: November 15, 2017, 01:29:44 AM »
Hi Charles,

thank you for the revised WinApi1 code. I was not sure if I asked a stupid question, but now I am glad that I asked. The structure of the code can be compared much better now with masm32. I suppose masm32 does many things in the background too. I will continue the Iczelion tutorials (they are very instructive for me) with the intention to use OxygenBasic's syntax and tools as much as possible and use assembly statements when they make some sense.

What is the effect of: addr ebx,bssdata ? I learned that the BSS segment holds data of uninitialized static and global variables, so I assume bssdata is handled internally by OxygenBasic?

Somewhere I read that Oxygen requires the ebx, ebp and esi registers, which can be saved/retrieved with pushad/popad. I assume some of the registers should not be used nevertheless after pushad?

Roland


Charles Pegge

  • Author
  • *****
  • Posts: 3290
    • Oxygen Basic
Re: Question about WinApi1.o2bas
« Reply #6 on: November 15, 2017, 05:04:14 AM »
Hi Roland,

All global/static variables and function vectors are addressed with the ebx register, and all local variables are similarly addressed using the ebp register. Therefore these registers should be preserved with care if your assembly code changes them.

To access global variables etc, the ebx register must hold the address of bssdata. It must be set for all extern/callback functions, such as wndproc. This is normally done internally by calling a low level procedure _mem, which does the same as addr ebx,bssdata.

Arnold

  • Sr. Member
  • ****
  • Posts: 469
Re: Question about WinApi1.o2bas
« Reply #7 on: November 19, 2017, 02:11:09 AM »
Hi Charles,

during my studies of the Iczelion tutorials I noticed an already forgotten discrepancy with constants using expressions:

'% WM_FINISH = WM_USER+0x100 '1280
'#define WM_FINISH WM_USER+100h '1280

'const WM_FINISH = WM_USER+0x100 '1280
sys WM_FINISH = WM_USER+0x100 '1280
print "WM_FINISH " WM_FINISH

The attached code of tut15 will work with const and sys and will not work correctly with % and #define neither with oxygen.dll provided at GitHub nor with the newer oxygen.dll in progress you provided some weeks ago. Will you get the same results and is there an explanation for the different behaviour? The problem occurs when using SendMessage with WM_FINISH.

Roland

Charles Pegge

  • Author
  • *****
  • Posts: 3290
    • Oxygen Basic
Re: Question about WinApi1.o2bas
« Reply #8 on: November 19, 2017, 04:12:20 AM »
Hi Roland,

%= precalculates the macro:
see if this makes a difference:

%= WM_FINISH = WM_USER+0x100 '1280

Arnold

  • Sr. Member
  • ****
  • Posts: 469
Re: Question about WinApi1.o2bas
« Reply #9 on: November 19, 2017, 06:50:34 AM »
Thank you, Charles. %= works fine. This is an excellent solution.

Roland
« Last Edit: November 21, 2017, 07:06:30 AM by Arnold »

Arnold

  • Sr. Member
  • ****
  • Posts: 469
Re: Question about WinApi1.o2bas
« Reply #10 on: November 21, 2017, 07:08:02 AM »
Hi Charles,

in the meantime I finished Iczelion's tutorial 33 (I skipped over some lessons after tut19). The demo works quite nice and I am looking forward to the last two lessons.

I would like to ask a question about the WinApi function RtlZeroMemory (ZeroMemory):
   RtlZeroMemory @ofn,sizeof ofn   'OPENFILENAME structure

I think this can be done with:
   ofn={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}

Are there other possible ways to fill the structure with zeros?

Roland
« Last Edit: November 21, 2017, 01:55:56 PM by Arnold »

Charles Pegge

  • Author
  • *****
  • Posts: 3290
    • Oxygen Basic
Re: Question about WinApi1.o2bas
« Reply #11 on: November 22, 2017, 01:51:19 AM »
Hi Roland,

Oxygen variables and memory blocks are already initialized with nulls when created, but if you need to clear a block specifically:

Code: [Select]
  macro FillBytes(name,count,value)
  =================================
  addr rsi,name
  mov rcx,count
  (
   dec rcx
   jl exit
   mov byte [rsi],value
   inc rsi
   repeat
  )
  end macro

With the o2 assembler, this will work for both 64 bit and 32 bit systems, and I will include it in generics.inc

« Last Edit: November 22, 2017, 01:58:22 AM by Charles Pegge »