Прямая запись в изображение на экране монитора.

Тема в разделе "WASM.ASSEMBLER", создана пользователем Zhelezka, 7 ноя 2008.

  1. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Pavia
    код в студию! хочу сам посмотреть что ты там напробовал и на тестировал. у одного вообще получилось что код на Delphi быстрее ассемблерного. но это поищи по названию здесь на форуме
    Y_Mur
    а про _asm вставки ты не слышал? я конечно же не за С, но тут чел открыто хочет по...мучать свой мозг
     
  2. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    max7C4
    Не сбивай с пути идущего (С) мудрость дзена ;) могу только повторить что это полюбому пойдёт в копилку просветления ;)
    полноценный асм гибче и удобнее убогих вставок. При написании библиотеки графических фукций не вижу никакого смысла оборачивать их в С, лучше поместить их в dll, com, lib и т.д. и вызывать из любого Hi levela по вкусу. А готовую библиотеку можно уже и в классы обернуть как в GDI+.
    если хоть немного рулишь в асме и элементарных приёмах оптимизации то возьми сам любой пробный код и сравни то что делают компили с тем что сделал бы сам на асме, особенно с FPU. Сразу увидишь множество ляпов, а если не способен на это, то чужие примеры не помогут :))
     
  3. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Y_Mur
    Да я знаю, что С любит хранить временные переменные в FPU, но я так же знаю, что MSVC любит делать и такую тупость, которой в Builer'е не наблюдается
    Код (Text):
    1. fld qword [xxxxxxxx]
    2. fstp qword [xxxxxxxx]
    но в целом код на си очень даже не плох. ты замучаешься в ручную подбирать команды для параллельного исполнения на двух конвейерах, а си с этим не плохо справляется. к тому же на асме можно писать хорошо и плохо (ровно как и на любом языке высокого уровня). Если правильно писать на асме, то слепить код по силе кода компилятора С довольно трудоемко, а сильнее - тем более. Но при всем при этом я тоже против использования языка высокого уровня, но и против изначального написания графической библиотеки. я лишь хочу сказать: "слепи игру на готовом, а потом переписывай ее сколько душе угодно". Совет очень даже хороший т.к. избранный им путь весьма труден, но поймет он это не сразу, а возвращаться будет уже поздно!
     
  4. murder

    murder Member

    Публикаций:
    0
    Регистрация:
    3 июн 2007
    Сообщения:
    628
    Шейдеры на ARB-ассемблере IMHO чень даже по-дзенски (особенно 2.0 где нет бранчей) и при этом позволяют создавать крутейшие эффекты.

    Прямой доступ к видеопамяти правильнее делать через DirectDraw (http://www.citforum.ru/programming/cpp/directdraw.shtml)
    Чтобы избавиться от затирания твоего изображения другими программами можно создать окно на весь экран с пустым обработчиком WM_PAINT.
     
  5. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    max7C4
    Представляешь - почти тебе поверил ;)
    Но оказалось просто некорректно поставленный тест :))
     
  6. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Y_Mur
    Ну прироста скорости в разы это не обещает, но правильно составленная программа может получить лишние 70-75 процентов времени выполнения за счет параллельного дешифрования и исполниния инструкций, а то что си гоняет данные между reg<>mem, то про кэш тоже не стоит забывать. к тому же не все так просто. не каждый код при такой оптимизации выдаст столько времени. код с командами сопроцессора может и пойдет, но не даст явного прироста из-за сопроцессора (оч он уж медлительный), а вот правильно сгенерированный код обработки двух независимых результатов в двух независимых группах регистров процессора - оч даже хорошо себя проявит.
     
  7. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    А ты попробуй взять любой осмысленный цикл на асме, заменить в нём обращение к регистру на обращение к памяти (которое стопудово кешировано поскольку обращение в цикле к одной и той же ячейке вместо регистра) и посмотри как это отразится на времени выполнения :))

    Гы-гы как раз в той ссылке что я привёл ранее в асм варианте совершенно очевидна возможность разбить цепочку зависимых команд предвыборкой следующего элемента мссива, а vs2005 /O2 release даже не попытался этого сделать, зато напихал хорошо параллелящихся, но совершенно бессмысленных команд :))

    Опять :))) во первых попробуй реализовать эти "медленные" команды через cpu и сразу поймёшь, что они быстрые, во вторых при ручном написании FPU кода можно шикарно параллелить не 2 а 3-7 команд ;) причём после небольшой практики написание такого параллельного кода становится совершенно естественным делом и при грамотных комментариях (позволяющих следить за состоянием FPU стека) этот код отлично читается. Хотя по моим наблюдениям компилятор и две то FPU команды редко когда распараллелить ухитряется :))
     
  8. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Y_Mur
    а ты попробуй в опциях оптимизацию включить
    Add: так. теперь возьми исходники ну к примеру StrongDC и попробуй их все переписать на асм, да еще и с распараллеливанием. когда закончишь - отпишись!
     
  9. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    max7C4
    каую тебе ещё оптимизацию кроме /O2 надо ? :))
    А ты попробуй не брать готовые исходники, а написать их с нуля на сях :)))
     
  10. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Y_Mur
    я к примеру. вот можешь попробовать написать с нуля. но функциональностью не меньше.
     
  11. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    max7C4
    Собственно я тебе толкую, не о том что на асме следует писать всё подряд (это только если душа просит :)), а о том, что графические библиотеки вещь статичная - вон те же GDI/GDI+ сколько лет не изменяются, а потому скорость разработки для них не столь принципиальна, зато принципиально качество работы. И поэтому их написание на асме самое оно :). Если всё же потребуется их перезаточить под другую или изменившуюся систему, то изменится только код выделяющий/копирующий массивы памяти, а собственно алгоритмы рисования изменений не потребуют или потребуют минимальной косметической корректировки под особенности новых версий процессора.
    А прикладные программы создаваемые по принципу "и так сойдёт, зато быстро состряпал" конечно лучше писать на хи-левеле :)
     
  12. Zhelezka

    Zhelezka New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2008
    Сообщения:
    103
    Я пробую с помощью bitblt, но пока ничего не получается,
    программа работает, но ничего не отображает.
    Допустим, есть приложение регистрирующее класс,
    создающее чёрное окно во весь экран,
    и при нажатии esc завершающееся:
    Код (Text):
    1. ...
    2. section 'data' data readable writeable
    3. ...
    4. bitmap_width db 800
    5. bitmap_height db 600
    6. bitmap dd 800*600 dup (0)
    7. ...
    8. section 'code' code readable executable
    9. ...
    10.   p_wndproc_destroy: ;------------------------------------------
    11.  
    12.     ;Что написать здесь?
    13.     invoke  PostQuitMessage, NULL
    14.     xor     eax,eax
    15.     ret
    16.  
    17.   p_wndproc_create:  ;------------------------------------------
    18.  
    19.     ;Что написать здесь?
    20.     xor     eax, eax
    21.     ret
    22.   p_wndproc_paint:  ;------------------------------------------
    23.  
    24.     ;Что написать здесь?
    25. ...
    Что надо добисать что-бы bitmap(800x600;32bit:RGB) скопировался с помощью bitblt в видео-память на монитор?
     
  13. murder

    murder Member

    Публикаций:
    0
    Регистрация:
    3 июн 2007
    Сообщения:
    628
    Приблизительно так
    Код (Text):
    1. DC=CreateDC("DISPLAY",0,0,0);
    2. DC2=CreateCompatibleDC(DC);
    3. SelectObject(DC2,CreateBitmap(800,600,1,32,bitmap));
    4. BitBlt(DC,0,0,800,600,DC2,0,0,SRCCOPY);
     
  14. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Или так:
    http://msdn.microsoft.com/en-us/library/dd145121(VS.85).aspx
     
  15. Zhelezka

    Zhelezka New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2008
    Сообщения:
    103
    Вот код, сам он длинный, но в основном всё стандартное...
    data-данные-важное в конце,
    code-код-важное в процедуре proc WndProc, lcl_wnd, lcl_msg, lcl_wParam, lcl_lParam,
    import-тут ничего нужного скорее всего нету...
    Изображение-всё закрашено опредёлённым цветом(красным),
    но на экране ничего не вижу...

    mainfile:
    Код (Text):
    1. format PE GUI 4.0
    2. entry p_code
    3.  
    4. include 'include\win32a.inc'
    5.  
    6. ;----------------------------------------------------------------------------------------------------;
    7. section 'data' data readable writeable
    8. include 'data\data.asm'
    9.  
    10. ;----------------------------------------------------------------------------------------------------;
    11. section 'code' code readable executable
    12. include 'code\code.asm'
    13.  
    14. ;----------------------------------------------------------------------------------------------------;
    15. section 'import' import data readable writeable
    16. include 'import\import.asm'
    data\data.asm:
    Код (Text):
    1. p_data:
    2.   wnd_class      db 'Game32',0      
    3.   wnd_title      db 'Game',0                  
    4.   wnd:
    5.   wnd_size       dd 0x04*0x0C            
    6.   wnd_style      dd CS_HREDRAW or CS_VREDRAW or CS_OWNDC
    7.   wnd_proc       dd WndProc                        
    8.   wnd_clswxtra   dd 0x0000        
    9.   wnd_wndextra   dd 0x0000                    
    10.   wnd_instance   dd 400000h                        
    11.   wnd_icon32     dd 0x0000                            
    12.   wnd_cursor     dd 0x0000                          
    13.   wnd_background dd BLACK_PEN                  
    14.   wnd_menu       dd 0x0000                        
    15.   wnd_classptr   dd wnd_class        
    16.   wnd_icon16     dd 0x0000                  
    17.  
    18.   mem_dc         dd 0x0000
    19.   wnd_dc         dd 0x0000
    20.   wnd_paint      PAINTSTRUCT
    21.  
    22.   msg            MSG                        
    23.  
    24.   wnd_id         dd 0x0000          
    25.   wnd_x          dd 0x0000
    26.   wnd_y          dd 0x0000
    27.  
    28.   mem_bitmap_id dd 0x0000
    29.  
    30.   mem_bitmap:
    31.  
    32.   dw             "BM"
    33.   dd             mem_bitmap_bits-mem_bitmap+(0x0800*0x0600*0x04)
    34.   dw             0x0000
    35.   dw             0x0000
    36.   dd             mem_bitmap_bits-mem_bitmap
    37.  
    38.   dd             mem_bitmap_bits-mem_bitmap
    39.   dd             0x0800
    40.   dd             0x0600
    41.   dw             0x0001
    42.   dw             0x0020
    43.   dd             0x0000
    44.   dd             0x0000
    45.   dd             0x0000
    46.   dd             0x0000
    47.   dw             0x0000
    48.   dw             0x0000
    49.  
    50.   mem_bitmap_bits db 0x0800*0x0600 dup (0x00,0xFF,0x00,0x00)
    code\code.asm:
    Код (Text):
    1. p_code:
    2.   invoke  GetModuleHandle, 0
    3.   mov     [wnd_instance], eax
    4.   invoke  LoadCursor, NULL, IDC_ARROW
    5.   mov     [wnd_cursor], eax
    6.  
    7.   invoke  RegisterClassEx, wnd
    8.  
    9.   invoke  GetSystemMetrics, SM_CXSCREEN
    10.   mov     [wnd_x], eax
    11.   push    eax
    12.   invoke  GetSystemMetrics, SM_CYSCREEN
    13.   mov     [wnd_y], eax
    14.   sub     eax, [wnd_y]
    15.   shr     eax, 1
    16.   pop     ebx
    17.   sub     ebx, [wnd_x]
    18.   shr     ebx, 1
    19.  
    20.   invoke  CreateWindowEx, WS_EX_TOPMOST, wnd_class, wnd_title, WS_POPUP or WS_VISIBLE, \
    21.                           ebx, eax, [wnd_x], [wnd_y], NULL, NULL, [wnd_instance], NULL
    22.   mov     [wnd_id], eax
    23.  
    24.   msg_loop:
    25.     invoke  GetMessage, msg , 0 , 0 ,  0
    26.     test    eax, eax
    27.     je      msg_end_loop
    28.  
    29.     invoke  TranslateMessage, msg
    30.     invoke  DispatchMessage, msg
    31.     jmp     msg_loop
    32.  
    33.  msg_end_loop:
    34.     mov     eax, [msg.wParam]
    35.  
    36.  
    37.     invoke  ExitProcess, eax
    38.     ret
    39.  
    40.  proc WndProc, lcl_wnd, lcl_msg, lcl_wParam, lcl_lParam
    41. ;==============================================================================
    42.  
    43.     cmp     [lcl_msg], WM_CREATE
    44.     je      p_wndproc_create
    45.  
    46.     cmp     [lcl_msg], WM_DESTROY
    47.     je      p_wndproc_destroy
    48.  
    49.     cmp     [lcl_msg], WM_PAINT
    50.     je      p_wndproc_paint
    51.  
    52.     cmp     [lcl_msg], WM_KEYDOWN
    53.     je      p_wndproc_keydown
    54.  
    55.     invoke  DefWindowProc, [lcl_wnd], [lcl_msg], [lcl_wParam], [lcl_lParam]
    56.     ret
    57.  
    58.  
    59.   p_wndproc_destroy: ;------------------------------------------
    60.  
    61.     invoke  PostQuitMessage, NULL
    62.     xor     eax,eax
    63.     ret
    64.  
    65.   p_wndproc_create:  ;------------------------------------------
    66.  
    67.     invoke  LoadBitmap,[wnd_instance],mem_bitmap
    68.     mov     [mem_bitmap_id],eax
    69.     xor     eax, eax
    70.     ret
    71.   p_wndproc_paint:  ;------------------------------------------
    72.  
    73.     invoke  BeginPaint,[wnd_id],wnd_paint
    74.     mov     [wnd_dc],eax
    75.     invoke  CreateCompatibleDC,[wnd_dc]
    76.     mov     [mem_dc],eax
    77.     invoke  SelectObject,[mem_dc],[mem_bitmap_id]
    78.     invoke  BitBlt,[wnd_dc],0,0,[wnd_x],[wnd_y],[mem_dc],0,0,SRCCOPY
    79.     invoke  DeleteDC,[mem_dc]
    80.     invoke  EndPaint,[wnd_id],wnd_paint
    81.     xor     eax, eax
    82.     ret
    83.  
    84.   p_wndproc_keydown: ;------------------------------------------
    85.  
    86.     mov     eax, [lcl_wParam]
    87.     cmp     eax, 27
    88.     jne     p_wndproc_noExit
    89.     invoke  SendMessage, [lcl_wnd] , WM_CLOSE , NULL, NULL
    90.  
    91.   p_wndproc_noExit:
    92.     xor     eax, eax
    93.     ret
    94.  
    95.  endp
    import\import.asm:
    Код (Text):
    1.   library kernel32,'KERNEL32.DLL',\
    2.           user32,'USER32.DLL',\
    3.           gdi32,'GDI32.DLL'
    4.  
    5. include 'include\apia\kernel32.inc'
    6. include 'include\apia\user32.inc'
    7. include 'include\apia\gdi32.inc'
     
  16. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Zhelezka
    Берёшь "дымок шамана" Olly и смотришь как работают/не работают твои функции, или добавляй после сомнительных условный MessageBox, который в случае ошибки выведет её GetLastError.
     
  17. Zhelezka

    Zhelezka New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2008
    Сообщения:
    103
    Я неправильно пользовался функцией LoadBitmap
    Место неё надо-было поставить
    Код (Text):
    1. invoke  CreateBitmap,0x0800,0x0600,0x0001,0x0020,mem_bitmap_bits
    теперь всё работает
     
  18. Zhelezka

    Zhelezka New Member

    Публикаций:
    0
    Регистрация:
    21 июл 2008
    Сообщения:
    103
    Код (Text):
    1. invoke  CreateBitmap,0x0800,0x0600,0x0001,0x0020,mem_bitmap_bits
    2. mov     [mem_bitmap_id],eax
    Программа работает, но как изменять пиксели
    Где именно будут содержаться сами пиксели, если извесен идентификатор bitmap'a:
    Код (Text):
    1. invoke  CreateBitmap,0x0800,0x0600,0x0001,0x0020,0x0000
    2. mov     [mem_bitmap_id],eax
     
  19. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Zhelezka
    Если Битмап грузится из файла или создаётся через api то легально добраться до пикселей можно только копируя их в/из свой буфер SetDIBits, GetDIBits.
    Чтобы напрямую рисовать в BITMAP своими функциями нужно делать наоборот - самому отдельно создавать массив пикселей и заголовок, а затем, после рисования, юзать их либо CreateDIBitmap либо StretchDIBits.
     
  20. murder

    murder Member

    Публикаций:
    0
    Регистрация:
    3 июн 2007
    Сообщения:
    628
    или GetBitmapBits, SetBitmapBits