TASM + OpenGL помогите найти ошибку

Тема в разделе "WASM.OpenGL", создана пользователем SerafimR, 20 мар 2009.

  1. SerafimR

    SerafimR New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2009
    Сообщения:
    24
    Помогите найти ошибку в приложении, аналогичная программа в FreePascal работает без ошибок.
    Вот код самой программы

    Код (Text):
    1. .586
    2. .model flat, stdcall
    3.  
    4. locals
    5.  
    6. include D:\Utilities\Writing\TASM5Plus\INCLUDE\win32.inc;
    7. include D:\Utilities\Writing\TASM5Plus\INCLUDE\OpenGL.inc;
    8. includelib D:\Utilities\Writing\TASM5Plus\LIB\import32.lib;
    9. includelib D:\Utilities\Writing\TASM5Plus\LIB\OpenGL.lib;
    10.  
    11.  
    12.  
    13. ;===Data segment======================================================================
    14. .DATA
    15.   WindowTitle     db 'Assembler', 0;
    16.   WindowClassName db 'Assembler', 0;
    17.   MenuName        db 0;
    18.  
    19.   IconName        db 'AppIcon', 0;
    20.  
    21.   WindowMsg     MSGSTRUCT < ? >;
    22.   wc            WNDCLASS  < ? >;
    23.  
    24.   include D:\TASM\Assembler_Modules\OpenGL_Init_Init_Data.asm;
    25.  
    26.  
    27.  
    28. ;===Uninitialized data segment========================================================
    29. .DATA?
    30.   hWndMain        dd ?;
    31.   Quit            dd ?;
    32.  
    33.   include D:\TASM\Assembler_Modules\OpenGL_Init_UnWrt_Data.asm;
    34.  
    35.  
    36.  
    37. ;===Code segment======================================================================
    38. .CODE
    39.  
    40. include D:\TASM\Assembler_Modules\OpenGL_Init_Pr_And_Fnc.asm;
    41.  
    42. Start :
    43.         call GetModuleHandle, 0;
    44.         test    eax, eax;
    45.     jz  Exit;
    46.  
    47.     mov  wc.clsHInstance, eax;
    48.  
    49.         mov  Quit, 0;
    50.  
    51.         ;---Registering window class--------------------------------------------------
    52.     mov   wc.clsStyle, CS_HREDRAW + CS_VREDRAW + CS_OWNDC;
    53.         mov   wc.clsLpfnWndProc, offset WindowProc;
    54.         mov   wc.clsCbClsExtra, 0;
    55.         mov   wc.clsCbWndExtra, 0;
    56.         mov   wc.clsHbrBackground, 0;
    57.         mov   dword ptr wc.clsLpszMenuName, offset MenuName;
    58.         mov   dword ptr wc.clsLpszClassName, offset WindowClassName;
    59.  
    60.         call  LoadIconA, wc.clsHInstance, offset IconName;
    61.         mov   wc.clsHIcon, eax;
    62.  
    63.         call  RegisterClassA, offset wc;
    64.         test    eax, eax
    65.     jz  Exit
    66.  
    67.  
    68.        
    69.         ;---CreatingWindow------------------------------------------------------------
    70.         ;push 0;
    71.         ;push wc.clsHInstance;
    72.         ;push 0;
    73.         ;push 0;
    74.         ;push 480;
    75.         ;push 640;
    76.         ;push CW_USEDEFAULT;
    77.         ;push CW_USEDEFAULT;
    78.         ;push WS_OVERLAPPEDWINDOW;
    79.         ;push offset WindowTitle;
    80.         ;push offset WindowClassName;
    81.         ;push 0;
    82.  
    83.         call CreateWindowExA, 0, offset WindowClassName, offset WindowTitle,\
    84.                           WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,\
    85.                   640, 480, 0, 0,\
    86.                   wc.clsHInstance, 0;
    87.  
    88.         test    eax, eax
    89.     jz  Exit
    90.  
    91.     mov  hWndMain, eax;
    92.         call ShowWindow, hWndMain, SW_SHOWNORMAL;
    93.         call UpdateWindow, hWndMain;
    94.  
    95.     ;---Message loop--------------------------------------------------------------
    96.         MsgLoop :
    97.                   call GetMessageA, offset WindowMsg, 0, 0, 0;
    98.                   call TranslateMessage, offset WindowMsg;
    99.                   call DispatchMessage, offset WindowMsg;
    100.  
    101.                   cmp Quit, 1;
    102.                   je  Exit;
    103.  
    104.                   jmp short MsgLoop;
    105.  
    106.  
    107.  
    108. Exit :
    109.     call    ExitProcess, 0
    110.     RET
    111.  
    112.  
    113.  
    114. ;===Procedures and functions==========================================================
    115. WindowProc proc uses    ebx edi esi, _hWnd : DWORD, WindowMessage : DWORD, _wParam : DWORD, _lParam:DWORD;
    116.         mov     eax, WindowMessage;
    117.  
    118.         cmp     eax, WM_SIZE;
    119.         je      resize;
    120.  
    121.         cmp     eax, WM_CREATE;
    122.         je      create;
    123.  
    124.     cmp     eax, WM_CLOSE;
    125.     je  close;
    126.  
    127.         call    DefWindowProc, _hWnd, WindowMessage, _wParam, _lParam;
    128.  
    129.         RET;
    130.  
    131. resize :
    132.          call ResizeWindow;
    133.          RET;
    134.  
    135. create :
    136.          ;---Writing OpenGL-----------------------------------------------------------
    137.          call WriteOpenGL;
    138.  
    139.          RET;
    140.  
    141. close :
    142.         call UnWriteOpenGL;
    143.         mov Quit, 1;
    144.    
    145.     RET;
    146.  
    147. WindowProc ENDP;
    148.  
    149.  
    150.  
    151. END Start;
    Вот код OpenGL.inc

    Код (Text):
    1. ;===Constants=========================================================================
    2. SIZE_OF_TPFD = 32;
    3.  
    4. PFD_DOUBLEBUFFER                = 00000001h;
    5. PFD_DRAW_TO_WINDOW              = 00000004h;
    6. PFD_SUPPORT_OPENGL              = 00000020h;
    7.  
    8. PFD_TYPE_RGBA                   = 0;
    9. PFD_MAIN_PLANE                  = 0;
    10.  
    11. GL_MODELVIEW                    = 1700h;
    12. GL_PROJECTION                   = 1701h;
    13.  
    14. GL_DEPTH_TEST                   = 0B71h;
    15. GL_PERSPECTIVE_CORRECTION_HINT  = 0C50h;
    16. GL_NICEST                       = 1102h;
    17. GL_SMOOTH                       = 1D01h;
    18.  
    19. ;===Types=============================================================================
    20. TPFD struc
    21.   nSize              dw ?;
    22.   nVersion           dw ?;
    23.   dwFlags            dw ?;
    24.   iPixelType         db ?;
    25.   cColorBits         db ?;
    26.   cRedBits           db ?;
    27.   cRedShift          db ?;
    28.   cGreenBits         db ?;
    29.   cGreenShift        db ?;
    30.   cBlueBits          db ?;
    31.   cBlueShift         db ?;
    32.   cAlphaBits         db ?;
    33.   cAlphaShift        db ?;
    34.   cAccumBits         db ?;
    35.   cAccumRedBits      db ?;
    36.   cAccumGreenBits    db ?;
    37.   cAccumBlueBits     db ?;
    38.   cAccumAlphaBits    db ?;
    39.   cDepthBits         db ?;
    40.   cStencilBits       db ?;
    41.   cAuxBuffers        db ?;
    42.   iLayerType         db ?;
    43.   bTPFDReserved      db ?;
    44.   dwLayerMask        dw ?;
    45.   dwVisibleMask      dw ?;
    46.   dwDamageMask       dw ?;
    47.  
    48. TPFD ends;
    49.  
    50.  
    51.  
    52. ;===Procedures and functions==========================================================
    53. extern  ChoosePixelFormat              : PROC;
    54. extern  SetPixelFormat                 : PROC;
    55. extern  wglCreateContext               : PROC;
    56. extern  wglMakeCurrent                 : PROC;
    57. extern  wglDeleteContext               : PROC;
    58. extern  ReleaseDC                      : PROC;
    59.  
    60. extern  glClearColor                   : PROC;
    61. extern  glEnable                       : PROC;
    62. extern  glHint                         : PROC;
    63. extern  glShadeModel                   : PROC;
    64.  
    65. extern  glViewPort                     : PROC;
    66. extern  glMatrixMode                   : PROC;
    67. extern  glLoadIdentity                 : PROC;
    68. extern  glOrtho                        : PROC;
    69. extern  glScalef                       : PROC;
    70. extern  glTranslatef                   : PROC;
    Вот код инициализированных данных для инициализации OpenGL

    Код (Text):
    1. MessageTitle              db   'OpenGL', 0;
    2. MessagePFDIsNotSetted     db   'Pixel format is not setted.', 0;
    3. MessageCHDCIsNotCreated   db   'Context is not created.', 0;        
    4.  
    5. pfd                       TPFD < 0 >
    6.  
    7. Zero                      dd 0.0;
    8. One                       dd 1.0;
    9. MinusOne                  dd - 1.0;
    10. AspectRatio               dd 0.75;
    11. ZeroEight                 dd 0.8;
    Вот код неинициализированных данных

    Код (Text):
    1. chdc              dd ?;
    2. chglrc            dd ?;
    3. iPixelFormat      dd ?;
    И вот код процедур инициализации OpenGL

    Если закомментировать вызовы всех процедур в процедуре ResizeWindow, то всё работает хорошо, окно создаётся, HDC получается, формат пикселя устанавливается и контекст создаётся, по крайней мере программа не выдаёт никаких сообщений об ошибке.
    Но как только разкомментирую call glViewPort, 0, 0, 640, 480;, программа пишет "Инструкция обратилась к памяти по адресу XXXX, память не может быть written. То же самое происходит с call glOrtho, MinusOne, One, MinusOne, One, MinusOne, One;. Все остальные вызовы в этой процедуре работают без ошибок.
    Что делать, в чём ошибка? И правильно ли я передаю вещественные параметры glClearColor, glOrtho, glScalef и glTranslatef?

    Компилирую программы скриптом

    Код (Text):
    1. D:\Utilities\Writing\TASM5Plus\BIN\tasm32  /ml /m5 /z /w2 /q Assembler.asm
    2. rem brcc32 window.rc
    3. D:\Utilities\Writing\TASM5Plus\BIN\tlink32 /Tpe /aa /c /o /V4.0 Assembler,Assembler.exe, , , , Resources\Assembler.res
    4. del *.obj
    5. del *.map
    Версия TASM'а - 5.0.
     
  2. SerafimR

    SerafimR New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2009
    Сообщения:
    24
    Странно, сейчас при сборке вообще пишет
    Error: Unresolved external 'glViewPort' referenced from module Assembler.asm, хотя я ничего не менял только закрыл Oper'у и перезапустил консоль.
    OpenGL.lib получил с помощью implib.exe -c -f -i OpenGL.lib OpenGL32.dll и glViewPort точно есть в OpenGL32.dll.
    С glOrtho же ничего не изменилось.
     
  3. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    SerafimR

    Зачем оперу закрыл?!

    Посмотри в hiew правильно ли у тебя там все адреса и импорт подставился для жл-ных функций.
     
  4. SerafimR

    SerafimR New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2009
    Сообщения:
    24
    С hiew я ещё работать не умею, но сейчас попробую разобраться.
    ALink, при компоновке строкой

    D:\Utilities\Writing\nasm-2.06rc1\alink\alink.exe -L D:\Utilities\Writing\TASM5Plus\LIB -oPE D:\Work\Programming\Programs\March\Assembler\Assembler.obj import32.lib OpenGL.lib

    вообще пишет

    Код (Text):
    1. Loading file D:\Work\Programming\Programs\March\Assembler\Assembler.obj
    2. Loading file D:\Utilities\Writing\TASM5Plus\LIB\import32.lib
    3. Loading file D:\Utilities\Writing\TASM5Plus\LIB\OpenGL.lib
    4. matched Externs
    5. matched ComDefs
    6. Unresolved external RegisterClassEx
    7. Unresolved external glViewPort
    Похоже, что дело в lib'ах или именах функций, но все остальные процедуры описываются без ошибок. Может быть есть какие-нибудь другие генераторы lib-файлов, кроме implib.exe, или остаётся только LoadLibrary, GetProcAddress и FreeLibrary?
     
  5. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    RegisterClassEx - такой функции нет. Есть RegisterClassExA и RegisterClassExW. Меняй.

    glViewPort - Port с маленькой - glViewport, хотя х.з. может ли это влиять на поиск по имени.
     
  6. SerafimR

    SerafimR New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2009
    Сообщения:
    24
    Да поменял в win32.inc RegisterClassEx на RegisterClassExA и ALink больше не жалуется на неё.
    В OpenGL.inc и в обращении к glViewPort поменял на glViewport - действительно помогло, остаётся только ошибка с glOrtho, но на неё линкеры не жалуются, что не могут её найти.
    При этом что странно, когда собираю ALink, что закомментирую строку
    call glOrtho, MinusOne, One, MinusOne, One, MinusOne, One;
    что нет - программа всё время выдаёт одну и ту же ошибку, при этом когда собираю TLink32, если закомментировать эту строку программа работает без ошибок, если разкомментировать - выдаёт ту же ошибку.

    И тут ещё такое, когда собираю TLink32, программа часто пишет "инструкция по адресу XXXX обратилась к памяти по адресу YYYY, память не может быть read", но иногода пишет, что не может быть written, когда собираю ALink, то программа всегда пишет память не может быть written.

    Попробовал ALink'ом собрать программу вообще без OpenGL выдаёт ту же самую ошибку, хотя когда собираю эту же программу TLink32, она запускается без ошибок.
     
  7. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    SerafimR
    Функция glOrtho использует соглашение вызова stdcall, принимает шесть параметров, каждый размером _восемь_ байт, ты передаешь шесть параметров по _четыре_ байта, как следствие портится стек при возврате, отсюда и "инструкция по адресу XXXX обратилась к памяти по адресу YYYY, память не может быть read".
     
  8. SerafimR

    SerafimR New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2009
    Сообщения:
    24
    С call glOrtho, MinusOne, One, MinusOne, One, MinusOne, One; проблема была в том, что ей нужны параметры размером dq, а я ей передавал dd. Сейчас дописал в инициализированных данных

    Код (Text):
    1. dqOne                     dq 1.0;
    2. dqMinusOne                dq - 1.0;
    и переписал процедуру в таком виде

    Код (Text):
    1. call glOrtho, dqMinusOne, dqOne, dqMinusOne, dqOne, dqMinusOne, dqOne;
    И теперь программа запускается без ошибок.

    Дальше добавил в соответствующие секции OpenGL.inc

    Код (Text):
    1. GL_DEPTH_BUFFER_BIT             = 00000100h;
    2. GL_COLOR_BUFFER_BIT             = 00004000h;
    3.  
    4. TRect struc
    5.   xLeft              dd ?;
    6.   yLeft              dd ?;
    7.   xRight             dd ?;
    8.   yRight             dd ?;
    9. TRect ends;
    10.  
    11. TPaintStruct struc
    12.   psHDC              dd ?;
    13.   fErase             dd ?;
    14.   rcPaint            TRect < ? >;
    15.   fRestore           dd ?;
    16.   fIncUpdate         dd ?;
    17.   rgbReserved        db 32 dup ( ? );
    18.  
    19. TPaintStruct ends;
    20.  
    21. global  glClear                        : PROC;
    22. global  SwapBuffers                    : PROC;
    Написал включаемый файл с процедурой изображения

    Код (Text):
    1. ImageWindow proc
    2.   call BeginPaint, hWndMain, offset ps;
    3.   call glClear, GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT;
    4.  
    5.   call SwapBuffers, chdc;
    6.  
    7.   call EndPaint, hWndMain, offset ps;
    8.  
    9.   RET;
    10. ImageWindow endp;
    И файл с неинициализированными данными к нему

    Код (Text):
    1. ps             TPaintStruct < ? >;
    И в оконной процедуре в соответствующих местах добавил

    Код (Text):
    1.     cmp     eax, WM_PAINT;
    2.     je      image;
    3.  
    4. image :
    5.     call ImageWindow;
    6.  
    7.     RET;
    По идее окно должно закраситься в белый цвет, но ничего не происходит, в FreePascal была такая же проблема, когда процедуры инициализации OpenGL, рисования и изменения размеров окна и соответствующие данные к ним выносил в отдельные модули и при обработке сообщений вызывал эти процедуры, решалось это тем, что код этих процедур напрямую вставлялся в обработку сообщений и все данные переносились в основной модуль программы. Сделал то же самое в TASM - всё равно не закрашивается в белый цвет.
    Быть может кто-нибудь сталкивался с подобной проблемой и знает как её решить, судя по тому, что она появляется и в FreePascal, и в TASM - это не проблема TASM'а, а вообще какая-то особенность работы OpenGL под Windows?
     
  9. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    SerafimR

    Ахтыж блин, ку_ку опередил) Да, все дело в sizeof(double).

    Вот, откапал свою прогу N-летней давности. Когда-то сам на асме для GL писал, так была проблема перевода вещественных чисел в флоат и дабл, точнее в их шестнадцатиричное представление. Пользуйся наздоровье:

    http://www.sendspace.com/file/4wefz2

    [edit]

    Хотя может тебе она и не нужна :)
     
  10. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    BeginPaint / EndPaint разве надо? Попробуй без них.
     
  11. SerafimR

    SerafimR New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2009
    Сообщения:
    24
    Ой q_q, извини, пропустил твоё сообщение.
    Пробовал без BeginPaint и EndPaint - то же самое. Они нужны чтобы окно не мерцало при его перемещении и при изменении размеров окна.

    Кстати там в TPFD третий и три последних параметра должны быть dd, а не dw, но и так тоже не рисует белым цветом.
     
  12. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    SerafimR

    Ну значит выкладывай сорец целиком.
     
  13. SerafimR

    SerafimR New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2009
    Сообщения:
    24
    Выкладываю программу на ассемблере в каком она сейчас виде, вместе с ней скрипт компиляции и OpenGL.inc. Также в папке FreePascal аналогичная программа на FreePascal, которая делает то же самое и при этом закрашивает окно белым цветом.
    Исполняемые файлы такие большие, т.к. к ним я довольно крупный значок присоединил.
     
  14. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    SerafimR

    Разве по WM_CREATE не надо передавать управление DefWindowProc?

    Надо возвращать 0 после WM_PAINT
     
  15. SerafimR

    SerafimR New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2009
    Сообщения:
    24
    В книге Кипа Р. Ирвина "Язык ассемблера для процессоров Intel" посмотрел DefWindowProc нужно вызывать только для обработки тех сообщений, котороые не обрабатывает WindowProc, т.е. если WindowProc обрабатывает сообщения WM_PAINT, WM_SIZE, WM_CREATE и WM_CLOSE, то не нужно для них вызывать DefWindowProc.
    В программе на FreePascal по этому правильнее вызов DefWindowProc включить в case в секцию else.
    При обработке сообщения WM_PAINT перед RET пробовал передать в eax 0 - программа по прежнему не закрашивает окно белым цветом.
     
  16. SerafimR

    SerafimR New Member

    Публикаций:
    0
    Регистрация:
    7 фев 2009
    Сообщения:
    24
    Кстати FreePascal может генерировать файлы на ассемблере для последующей компиляции. Выложил то, что выдаёт FreePascal для TASM'а и MASM'а. Может быть это поможет. Только TASM'ом он не компилируется, он пишет

    Код (Text):
    1. THREADVARLIST_P$WINDOWS_PROGRAM:
    2. **Error** Windows_Program_TASM.s(392) CS unreachable from current segment
    3.     END
    4. *Warning* Windows_Program_TASM.s(521) Open segment: _CODE
     
  17. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    SerafimR

    Я кажется знаю в чем дело, но я не понимаю как это работает в паскале)

    Короче, убери обработчик WM_CREATE, а инициализацию пиксельформата и самого OpenGL сделай в главной ветке, сразу после CreateWindow.
     
  18. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Или в обработчике WM_CREATE поменять "call GetDC, hWndMain" на "call GetDC, _hWnd".
     
  19. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    Бугага, кстати да. hWndMain-то еще не инициализирован. Но всеравно, там вроде бы то ли GetDC, то ли SetPixelFormat не должен сработать пока WM_CREATE не закончит работу. И да, все-таки отработай WM_CREATE через DefWindowProc.
     
  20. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    _DEN_
    С какого перепугу?

    Политика сообщений такова, что если мы делаем свою обработку, то возвращаем результат (как правило ноль). Если не обрабатываем, то передаём дефолтному обработчику.