аналоговые часы Код (ASM): ; GUI # include win64a.inc W = 256 H = 256 .code WinMain proc local hbrBackground:qword local msg:MSG xor ebx,ebx mov esi,IMAGE_BASE mov edi,offset AppName mov qword ptr[rsp+28h],LR_LOADFROMFILE mov [rsp+20h],rbx mov edx,offset BmpName invoke LoadImage,esi,,0,0 invoke CreatePatternBrush,eax mov hbrBackground,rax mov ecx,offset FileName invoke LoadCursorFromFile push rax ;hIconSm push rdi ;lpszClassName push rbx push hbrBackground push rax ;hCursor push rax ;hIcon push rsi ;hInstance push rbx ;cbClsExtra & cbWndExtra pushaddr WndProc ;lpfnWndProc push sizeof WNDCLASSEX;cbSize & style invoke RegisterClassEx,esp ;addr WNDCLASSEX push rbx push rsi ;rsi=400000h shl esi,9 ;rsi=CW_USEDEFAULT push rbx push rbx push H+20 push W push rsi push rsi sub esp,20h mov r9d,WS_OVERLAPPED or WS_VISIBLE or WS_CAPTION or WS_SYSMENU invoke CreateWindowEx,0,edi,edi mov hWin,rax lea edi,msg @@: invoke GetMessage,edi,NULL,0,0 invoke DispatchMessage,edi jmp @b WinMain endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM local ps:PAINTSTRUCT local hdc:HDC local hpen:DWORD local hPenOld:DWORD local hBrush:DWORD local hBrushOld:DWORD local X:DWORD local temp2:DWORD local Time:SYSTEMTIME mov hWnd,rcx cmp edx,WM_CREATE je wmCREATE cmp edx,WM_PAINT je wmPAINT cmp edx,WM_DESTROY je wmDESTROY leave jmp NtdllDefWindowProc_ wmDESTROY:;уничтожаем таймер invoke timeKillEvent,hTimer invoke RtlExitUserProcess,NULL wmCREATE:mov qword ptr[rsp+20h],TIME_PERIODIC mov r8d,offset TimeProc invoke timeSetEvent,1000,1000,,777 mov hTimer,rax lea ecx,Time invoke GetLocalTime movzx eax,Time.wHour sub eax,12 jnc @f add eax,12 @@: cvtsi2ss xmm0,eax movss Hour,xmm0 movzx eax,Time.wMinute cvtsi2ss xmm0,eax movss Minute,xmm0; преобразовать целые минуты из SYSTEMTIME в вещественные movzx eax,Time.wSecond cvtsi2ss xmm0,eax movss Second,xmm0; преобразовать целые секунды из SYSTEMTIME в вещественные mulss xmm0,const1_60; домножить секунды на 1/60 и добавить к минутам addss xmm0,Minute movss Minute,xmm0;минуты с учетом секунд mulss xmm0,const1_60; домножить минуты на 1/60 и добавить к часам addss xmm0,Hour movss Hour,xmm0;часы с учетом минут jmp wmBYE wmPAINT:lea edx,ps invoke BeginPaint;,hWnd mov hdc,rax invoke CreatePen,PS_SOLID,2,6464FFh;(255,100,100) ;заводим красный карандаш толщиной 2 для рисования секундной стрелки mov hpen,eax invoke SelectObject,hdc,eax;hpen mov hPenOld,eax;сохраняем старый карандаш invoke MoveToEx,hdc,H/2,W/2,NULL;от точки в середине экрана рисуем стрелку длиной 100 точек movss xmm0,temp;pi/30 mulss xmm0,Second;секунды movss temp2,xmm0 invoke cosf mulss xmm0,Second_arrow;100*cos(секунды*pi/30) cvtss2si eax,xmm0 mov X,eax;X=100*cos(секунды*pi/30) movss xmm0,temp2 invoke sinf mulss xmm0,Second_arrow;100*sin(секунды*pi/30) cvtss2si edx,xmm0;edx=100*sin(секунды*pi/30) add edx,H/2 mov r8d,W/2 sub r8d,X invoke LineTo,hdc invoke DeleteObject,hpen;удаляем карандаш, который создали для секундной стрелки ;минутная стрелка invoke CreatePen,PS_SOLID,7,808080h;(128,128,128) ;заводим серый карандаш толщиной 7 для рисования минутной и часовой стрелки mov hpen,eax invoke SelectObject,hdc,eax invoke MoveToEx,hdc,W/2,H/2,NULL ;------------------------------------------------------ movss xmm0,temp;pi/30 mulss xmm0,Minute;минуты*pi/30 movss temp2,xmm0 invoke cosf mulss xmm0,Minute_arrow;75*cos(минуты*pi/30) cvtss2si eax,xmm0 mov X,eax;X=100*cos(минуты*pi/30) movss xmm0,temp2 invoke sinf mulss xmm0,Minute_arrow;75*sin(минуты*pi/30) cvtss2si edx,xmm0;Y=50*sin(минуты*pi/30) add edx,H/2;119 mov r8d,W/2;119 sub r8d,X ;------------------------------------------------------- invoke LineTo,hdc ;часовая стрелка invoke MoveToEx,hdc,W/2,H/2,NULL ;------------------------------------------------------ movss xmm0,Hour;часы mulss xmm0,temp1;pi/6 movss temp2,xmm0 invoke cosf mulss xmm0,Hour_arrow;50*cos(минуты*pi/6) cvtss2si eax,xmm0 mov X,eax;X=50*cos(минуты*pi/6) movss xmm0,temp2 invoke sinf mulss xmm0,Hour_arrow;50*sin(минуты*pi/6) cvtss2si edx,xmm0;Y=50*sin(минуты*pi/6) add edx,H/2;119 mov r8d,W/2;119 sub r8d,X ;------------------------------------------------------- invoke LineTo,hdc invoke SelectObject,hdc,hPenOld;возвращаем системе старый карандпш invoke DeleteObject,hpen;удаляем карандаш, который создали для минутной и часовой стрелки ;заглушка в центре циферблата invoke CreatePen,PS_SOLID,3,0AAAAAAh;(170,170,170) создаем светлосерый карандаш для рисования ;заглушки в центре циферблата mov hpen,eax invoke SelectObject,hdc,eax mov hPenOld,eax invoke CreateSolidBrush,505050h;80,80,80 создаем серую кисть для рисования заглушки в центре циферблата mov hBrush,eax invoke SelectObject,hdc,eax;hBrush mov hBrushOld,eax invoke Ellipse,hdc,123,123,135,135; рисуем кольцо в центре циферблата invoke SelectObject,hdc,hBrushOld;возвращаем системе старую кисть invoke DeleteObject,hBrush;удаляем кисть, которую создали для заглушки в центре циферблата lea edx,ps invoke EndPaint,hWnd;возвращаем системе дескриптор устройства wmBYE: leave retn WndProc endp ; Обработчик вытокоточного таймера TimeProc proc uTimerID:QWORD,uMsg:QWORD,dwUser:QWORD,dw1:QWORD,dw2:QWORD movss xmm0,const1 addss xmm0,Second movss Second,xmm0;прошла секунда --> добавить 1 к секундам movss xmm0,Minute addss xmm0,const1_60 movss Minute,xmm0;прошла секунда --> добавить 1/60 к минутам movss xmm0,Hour addss xmm0,const1_3600 movss Hour,xmm0;прошла секунда --> добавить 1/3600 к часам invoke InvalidateRect,hWin,0,TRUE leave retn TimeProc endp ;----------------------------------------------------------- .data Second dd ? Minute dd ? Hour dd ? const1_60 dd 0.0166666666666666666666666667;1/60 доля минут в часе const1_3600 dd 0.0002777777777777777777777778;1/3600 доля секунд в часе temp dd 0.1047197551196597746154214461;pi/30 минут, секунд в радиане temp1 dd 0.5235987755982988730771072305;pi/6 часов в радиане Second_arrow dd 100.0 Minute_arrow dd 75.0 Hour_arrow dd 50.0 AppName db 'Часы',0 FileName db "br_Rabbit3.cur",0 BmpName db "clock256.bmp",0 hWin dq ? hTimer dq ? const1 dd 1.0 end Во вложении asm-/bmp-/cur-/exe-файл
asm-файл Код (ASM): ; GUI # include win64a.inc TIMER_ID = 10 IDB_MYBITMAP equ 100 .code WinMain proc local msg:MSG xor ebx,ebx mov esi,IMAGE_BASE mov edi,offset AppName mov ecx,offset FileName invoke LoadCursorFromFile push rax ;hIconSm push rdi ;lpszClassName push rbx push COLOR_WINDOW push rax ;hCursor push rax ;hIcon push rsi ;hInstance push rbx ;cbClsExtra & cbWndExtra pushaddr WndProc ;lpfnWndProc push sizeof WNDCLASSEX;cbSize & style invoke RegisterClassEx,esp ;addr WNDCLASSEX push rbx push rsi ;rsi=400000h shl esi,9 ;rsi=CW_USEDEFAULT push rbx push rbx push 110+10 push 403+10 push rsi push rsi sub esp,20h mov r9d,WS_OVERLAPPED or WS_VISIBLE or WS_CAPTION or WS_SYSMENU invoke CreateWindowEx,0,edi,edi lea edi,msg @@: invoke GetMessage,edi,NULL,0,0 invoke DispatchMessage,edi jmp @b WinMain endp WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM local ps:PAINTSTRUCT local hdc:dword local Time:SYSTEMTIME local hMemDC:dword mov hWnd,rcx cmp edx,WM_CREATE je wmCREATE cmp edx,WM_PAINT je wmPAINT cmp edx,WM_DESTROY je wmDESTROY cmp edx,WM_TIMER je wmTIMER leave jmp NtdllDefWindowProc_ wmDESTROY:;уничтожаем таймер #10 invoke KillTimer,,TIMER_ID mov ecx,hBitmap invoke DeleteObject invoke RtlExitUserProcess,NULL wmCREATE:invoke SetTimer,,TIMER_ID,1000,NULL invoke LoadBitmap,IMAGE_BASE,IDB_MYBITMAP mov hBitmap,eax wmTIMER:lea ecx,Time invoke GetLocalTime movzx eax,Time.wSecond mov [rsp+20h],rax movzx r9d,Time.wMinute movzx r8d,Time.wHour mov ecx,offset buffer lea edx,fmtstr invoke wsprintf invoke InvalidateRect,hWnd,NULL,TRUE jmp wmBYE wmPAINT:lea edx,ps invoke BeginPaint;,hWnd mov hdc,eax invoke CreateCompatibleDC,eax mov hMemDC,eax mov edx,hBitmap invoke SelectObject,eax xor edi,edi sub esp,40h @@: mov eax,hMemDC mov [rsp+28h],rax and qword ptr[rsp+38h],0 mov qword ptr[rsp+40h],SRCCOPY movzx eax,buffer[rdi] and eax,0Fh imul eax,53 mov [rsp+30h],rax mov qword ptr[rsp+20h],82 imul edx,edi,49 invoke BitBlt,hdc,,0,53 inc edi cmp edi,7 jbe @b add esp,40h invoke DeleteDC,hMemDC lea edx,ps invoke EndPaint,hWnd;возвращаем системе дескриптор устройства wmBYE: leave retn WndProc endp .data AppName db 'Часы',0 FileName db "br_Rabbit3.cur",0 fmtstr db "%02d:%02d:%02d",0 hBitmap dd ? buffer db 50 dup(?) end rc-файл Код (C++): #define IDB_MYBITMAP 100 IDB_MYBITMAP BITMAP "03.bmp" Во вложении asm-/bmp-/cur-/rc-/exe-файл
Прикольно. https://www.virustotal.com/gui/file...ceed35d5289905b0095fbe2214ed8356d54?nocache=1 6 антивиря быкуют. Сделал контрол 7ми сегментного индикатора немного по другому, хранятся только атласы самих сегментов, а шрифт отдельно задаётся. Реально лучше заморочится, чтобы потом класс использовать в других проектах. Для калькулятора делал. Ещё как можно решить проблему антиалиасинга?
Особенно прекрасны вот такие кундштюки: Хоть бы один процентик могучий искусственный интеллект скинул, малейший шанс для себя не выглядеть гавном.
При запуске исполнимого файла timer02.exe в окошке не отображаются цифры ??? Windows 7 64 бит timer01.exe работает нормально, часы отображаются.
DOSAsm386, при сборке ехе, в том же каталоге, где находятся timer02.asm и timer02.rc должен находится файл 03.bmp, или путь к файлу нужно подправить в timer02.rc У 03.bmp глубина цвета 8 (256 цветов), так что картинка должна отображаться даже на слабеньких видеоадаптерах и мониторах
? На сттью на Хабр по книге рабочая, а ссылка на саму книгу, если это подразумевалось, то вот она из статьи https://www.xorpd.net/pages/xchg_rax/snip_00.html
А зачем х86-64? Нормально х86-32 (386) и WinAPI чтобы и на 95 заработало. Не важно что там у кого-то устарело. На ХР точно должно работать.
Зачем? Сейчас её днём с огнём не сыщешь. Для чего тянуть поддержку мёртвых систем? Новичкам правильнее учить сразу и 32х-битный, и 64х-битный ассемблеры, чтобы видеть различия и приобретать опыт разработки под актуальные архитектуры. Знание 64х-битного ассемблера низкоуровневым разработчикам пригодится намного сильнее, нежели поддержка Win95 и WinXP.
Зачем? Зачем? А какой смысл от новых систем, если нет никакого преимущества. Вот в вынь 10 директха 12 есть, игры с лучшим графоном, тут всё понятно, вопросов нет. А тут просто часы какие-то. Зачем тут х64? Какой в этом смысл? А то многие думают что х86-64 в два раза быстрей х86-32. Нет конечно, плюс приложение очень лёгкое, с оптимизацией можно не заморачиваться. Значит надо сделать так, чтобы и на 486 Win95 заработало, может кому-то надо. Вон кто-то и на 5150 сейчас что-то делает.
Смысл наверное в том, что это скорее дидактический материал, чем программный продукт. Если кто-то в быту использует хеловорлд для каких-то утилитарных целей, то он неправ.
Ну тогда и для х86-32 надо вариант сделать. ЗЫ Ещё калькулятор надо сделать с 7ми сегментным контролом и интерактивными кнопками и на двоично-десятичной логики и только 386 без использовании FPU. Чтобы 486SX, 386DX - Win95 или даже Win3.1, т.е. только старый WinAPI. ЗЫЫ В 7ке, 10ке калькулятор полное говно, делал не то чтобы дебил, но для нормальных программистах полный шлак, не куда не годен. Надо переделать. И чтобы ХР точно работал. Изобретём калькулятор? (с)
В чисто практическом плане сам интерфейс кнопочного калькулятора на экране ПК не самое удачное решение, особенно для нормальных программистов. С настоящим материальным кнопочником он все равно в удобстве не сравнится. И вообще имхО основное назначение виндового calc.exe - evaluate'ить выражения, в том числе со скобками, на ctrl-v. Отсюда кстати программистская версия калькулятора (js, макрос для emeditor): Код (C): function decimalToHexString(number){ if(number < 0){ number = 0xFFFFFFFF + number + 1; } return number.toString(16).toUpperCase(); } function multiline_calc() { var sel_left = document.selection.GetTopPointX(eePosView); var sel_top = document.selection.GetTopPointY(eePosView); var sel_right = document.selection.GetBottomPointX(eePosView); var sel_bottom = document.selection.GetBottomPointY(eePosView); var sel_mode = document.selection.mode & eeModeMask; var lines = document.selection.text.split('\r\n'); for (var i=0;i<lines.length;i++) { if (lines[i].length != 0) { if (sel_mode == eeModeBox) { document.selection.SetActivePoint(eePosView,sel_left,sel_top+i); document.selection.SetAnchorPoint(eePosView,sel_right,sel_top+i); } else { document.selection.SetActivePoint(eePosView,1,sel_top+i); document.selection.EndOfLine(sel_top+i); } clipboardData.setData('Text',lines[i] + '=0x' + decimalToHexString(eval(lines[i]))); document.selection.Paste(0); } } } multiline_calc();
f13nd, > evaluate'ить выражения, в том числе со скобками Лет 10%15 назад был популярным VB, так вот там можно было в десяток строк такой калк собрать, он умел вычислять любой вложенности выражения матан есчо и с системными для среды командами по типу GetTime(). Наверно самая интересная его фишка, он интерпретировал сам себя.
f13nd, На счёт петон я не знаю. Но фишка годная была, тем более что там можно было вирт машину компилить. Я такой калк тоже собирал, но как это работало я не знаю, всмысле на системном уровне. Там мышем в основном всё делалось