![]() |
Программирование на ассемблере для начинающих. Ассемблер gas под linux, fasm под windows, tasm под dos, и многое другое. |
|---|
Программа на fasm. Тест на знание неправильных глаголов английского языка.
;;; в общем сия программа предназначена для зубрёжки неправильных глаголов ;;; для функционирования необходим текстовый файл под названием ;;; 'irregverbs.txt' и иконка (я перерисовал иконку из examples/minipad) ;;; структуру текстового файла смотрите в самом файле - там ничего сложного ;;; ;;; кстать, сменил ассемблянт на fasm 1.67.26 (вынужденно) ;;; и пришлось вносить некоторые изменения в синтаксисе, а именно ;;; 1) в директиве include более не нужно писать '%include%\win32a.inc' (пример), а просто 'win32a.inc' ;;; т.е. '%include%\' убираем ;;; 2) при описании процедур вместо ;;; # proc MyProc, param1,param2 ;;; # enter ;;; # push ebx esi edi ;;; # ; - код процедуры ;;; # pop edi esi ebx ;;; # return ;;; пишем следующим образом ;;; # proc MyProc param1,param2 (запятая не имеет значения - можно и поставить) ;;; # push ebx esi edi ;;; # ; - код процедуры ;;; # pop edi esi ebx ;;; # ret ;;; # endp ;;; с другими изменениями в синтаксисе я пока не сталкивался ;;; format PE GUI 4.0 ; - как обычно формат портабельный исполнимый, версия гуи 4,0 entry start ; - точка входа метка start include 'win32a.inc' ; подключаем инклуд ;;; здесь мы описываем константы - так проще. Это всё объекты блока ресурсов. Названия при ассемблировании будут заменены числами. IDD_DLG = 37 ;# IDE_FIRST = 101 ;# IDE_SECOND = 102 ;# названия придумываем исключительно из IDE_THIRD = 103 ;;; ;# соображений удобства; IDS_DESCRIPTION = 201 ;# IDE_бла-бла-бла - editbox IDS_SCORES = 202 ;; ;# IDS_ - static IDS_FIRST = 203 ;# IDB_ - button IDS_SECOND = 204 ;# IDD_ - dialogbox IDS_THIRD = 205 ;;; ;# числа тоже можно поставить любые IDB_NEXT = 401 ;# (главное не запутаться и не перегибать) IDB_RESET = 402 ;# ;;; далее определяем структуры и макросы ;;; для тех кто не знает - определение структур и макросов не занимает в памяти ни байта ;;; это всё придумано для удобства ;;; там где будет определён макрос - ассемблянт вставит его код ;;; ну а структура - это просто набор меток и данных которые действительны только при ;;; инициализации структуры (переменной как структуры) ;;;;; fparam - структура, содержащая параметры файла struc fparam ; имя структуры { .path db 'irregverbs.txt',0 ; путь к текстовому файлу с глаголами (в фаловой системе) .strings db 0 ; строк (всего) .size dd 0 ; размер файла в байтах .pointer dd 0 ; указатель на область памяти - начало файла в памяти .true dw 0 ; правильных .false dw 0 ; неправильных .done db 0 ; сделано .pointerpos dd 0 ; позиция указателя .first rb 20 ; первая фрорма глагола .second rb 20 ; вторая .third rb 20 ; третья .description rb 216 ; описание } ;;;; макрос readbsn читает строку по адресу в esi по байтам в строку с адресом mspoint ;;;; до тех пор пока не встретит в строке symbol ;;;; встретив символ переходит на код, идущий вслед за макросом ;;;; изменения: esi,al,ecx; стэк не используется macro readbsn mspoint,symbol,metka ;; \ readbsn = имя макроса, mspoint = указатель на строку, { ;;; \ symbol = символ, metka = метка xor ecx,ecx ; обнуляем ecx @@: ; анонимная метка - начало цикла lodsb ; читаем байт (из строки садресом в esi) test al,al ; тестим (or al,al - только операнды остаются неизменными) jz metka ; если ноль, прыжок на метку metka cmp al,symbol ; сравниваем с символом je @f ; если совпадает, выходим из цикла mov byte [mspoint+ecx],al ; если нет, помещаем байт по адресу [mspoint+ecx] inc ecx ; увеличиваем ecx на 1 jmp @b ; переходим в начало цикла @@: ; анонимная метка - выход из цикла } ; раз уж начал использовать анонимные метки - расскажу про них вкратце ; @@: - определение анонимной метки - их модно определить великое множество ; @b, @r - ссылается на ближайшую предыдущую анонимную метку (before) ; @f - на ближайшую последующую анонимную метку (follow) ; например: ;# ;# @@: <----------------+ ;# ; some code | ;# jmp @b ---------+ ;# ; some code ;# jmp @f ---------+ ;# ; some code | ;# @@: <----------------+ ;# ;;;; макрос countbn подсчитывает количество символов symbol ;;;; в строке с адресом в esi до тех пор пока ;;;; не встретит null, результат подсчёта в cl ;;;; изменения: esi, al, cl; стэк не используется macro countbn symbol ; countbn - имя макроса, symbol - символ { xor cl,cl ; обнуляем cl @@: ; анонимная метка - начало цикла lodsb ; читаем байт (из строки садресом в esi) test al,al ; тестим jz @f ; если ноль, то выходим из цикла cmp al,symbol ; сравниваем с символом jne @b ; если не совпадает, то идём в начало цикла inc cl ; если совпадает (на самом деле не не совпадает) - увеличиваем cl на 1 jmp @b ; переход в начало цикла @@: ; анонимная метка - выход из цикла, выходим только если прочитали ноль } ;;;; макрос sevennull онуляет строки first,second,third ;;;; и f.first,f.second,f.third,f.description ;;;; обнуляет 20 символов начиная с начала (215 для обоих description) ;;;; изменения: eax, ebx, ecx, edx; стэк не используется macro sevennull ; имя макроса { mov ecx,20 ; помещаем в ecx 20 - 20 символов подлежат обнулению @@: ; анонимная метка начало цикла mov byte [first+ecx],0 ; ноль по адресу first+ecx mov byte [second+ecx],0 ; аналогично: 0 -> [second+ecx] mov byte [third+ecx],0 ; 0 -> [third+ecx] loop @b ; уменьшаем ecx на 1, если не равен нулю, то прыжок в начало цикла (@@:) mov ecx,20 @@: ;;| mov byte [f.first+ecx],0 ;;| mov byte [f.second+ecx],0 ;;| то ж самое, только f.first, f.second, f.third mov byte [f.third+ecx],0 ;;| loop @b ;;| mov ecx,215 ; @@: ; mov byte [f.description+ecx],0 ; тут тоже тока для f.description loop @b ; } ;;;; макрос cmptstr сравнивает две строки указатель на первую в esi, на вторую в edx ;;;; в случае несовпадения переходит на метку fmetka ;;;; при окончании строки (символ null) переходит на nmetka ;;;; изменения: edi, esi; стэк не используется ; esi=first, edi=f.first macro cmptstr fmetka ; cmptstr = имя макроса, fmetka = метка (на неё прыгаем, если не равны) { @@: ; анонимная метка - начало цикла cmpsb ; сравниваем символы по адресам в esi и edi; esi+1, edi+1 jne fmetka ; если не равны - переходим на метку fmetka cmp byte [esi],0 ; сравниваем с нулём jz @f ; follow ; если ноль - выход из цикла jmp @b ; before ; переход в начало цикла (если равны и не ноль) @@: ; аннонимная метка - выход из цикла } section '.data' data readable writeable ; секция данных читаемых и писуемых, бла-бла-бла, всё как обычно first rb 20 ; резервируем 20 байт second rb 20 ; -"- third rb 20 ; -"- f fparam ; определяем переменную f как структуру fparam strue db 'true',0 ; 3-е ASCIIZ строки sfalse db 'false',0 ; sscores db 'done/all = 000/000',0Ah,'true/false = 000/000',0 ;11,12,13/15,16,17 32,33,34/36,37,38 ; числа выписаные после переменной в коментарии - смещение в адресном пространстве ; относительно sscores (sscores указывает на превый символ строки) ; нулей 000/000 - они нам пригодятся впоследствии ; 0Ah - шестнацатиричный код перевода строки в ASCII (enter короче говоря) bytescount dd ? ; для чтения файла нужна sherror db 'mission faild',0 ; 3 строки выдаваемые при возникновении ошибок saerror db 'allocation faild',0 soerror db 'file opening faild',0 slast db 'больше нетути',0 ; сообщение о конце файла last db 0 ; идентифицирует последнюю строку snull db 0 ; пустая строка section '.code' code readable executable ; секция кода читаемая исполнимая бла-бла-бла start: ; метка начала кода - святая святых ;############################################################### ###########################; ;### выделение памяти под файл и чтение из файла в эту память #############################; invoke CreateFile,f.path,GENERIC_READ,0,0,OPEN_EXISTING,0,0 ; API функция - создает файл или открывает существующий (и не только). ; Передаваемые параметры: ; 1 - указатель на ASCIIZ строку содержащую путь к файлу в файловой системе, ; 2 - тип доступа к объекту - любая комбинация следующих флагов: ; 0 - "определяет аттрубуты файла не присоединяясь к нему" - вот и думай что это значит??? (наверное просто получить хендл и всё) ; GENERIC_READ - доступ по чтению ; GENERIC_WRITE - доступ по записи ; 3 - набор флагов разделяющих объект ; 0 - не делить объект (пока мы не закроем хендл из файла никто более ничего не прочитает) ; FILE_SHARE_DELETE - (работает тока у NT) - тоже что и 0, но после закрытия файл(объект) будет удалён ; FILE_SHARE_READ - доступен другим для чтения ; FILE_SHARE_WRITE - доступен другим для записи ; 4 - могут ли процессы потомки использовать указатель (0 - не могут) ; 5 - совершаемое действие (один из флагов) ; CREATE_NEW - создает новый файл (если существут - неудача) ; CREATE_ALWAYS - создает новый файл (если существут - перезаписывает) ; OPEN_EXISTING - открывает существующий (нету - неудача) ; OPEN_ALWAYS - открывает файл (если нету - создает) ; TRUNCATE_EXISTING - открывает файл, при этом обнуляет его размер (должен быть уровень доступа GENERIC_WRITE, если файл не существует - неудача) ; 6,7 - не важно (смотри MSDN) mov edi,eax ; сохраняем хендл файла в edi (ошибки здесь не рассматриваем, если всё норм - то хендл возвращается функцией в eax) invoke GetFileSize,edi,0 ; API-функция - берём размер файла ; параметры: 1) - хендл(указатель) файла ; 2) - максимальный размер файла mov [f.size],eax ; в eax имеем возвращённыйф размер файла, сохраняем его в [f.size] inc eax ; увеличивам eax на 1 для выделения памяти ; VirtualAlloc выделяет память и обращает выделеный участок в нули, теперь в конце у нас будет 0 ; (в конце выделеной области 0, а не последний символ файла, для этого и увеличиваем на 1) ; выдляем память для чтения файла в RAM ; используем функцию VirltualAlloc, она позволяет зарезервировать участок памяти ; заданого размера и обращает эту память в нули ; параметры: ; 1) начальный адрес региона, ; 2) размер региона (в байтах разумеется), ; 3) тип резервирования: а) MEM_COMMIT - эта память может быть сброшена в файл подкачки ; б) MEM_RESERVE - этот участок памяти не может быть сброшен в файл подкачки ; он будет присутствовать в физической памяти всегда, пока эту память процесс не ввысвободит ; в) MEM_TOP_DOWN - зарезервировать виртуальную память, ; которая будет соответствовать максимально возможному физическому адресу; ; 4) тип доступа к памяти: PAGE_READONLY ; PAGE_READWRITE ; PAGE_EXECUTE позволяет передавать управление этому региону попытка чтения или записи приводит к нарушению прав доступа. ; PAGE_EXECUTE_READ ; PAGE_EXECUTE_READWRITE ; PAGE_NOACCESS ; (я надеюсь тут всё понятно) invoke VirtualAlloc,0,eax,MEM_COMMIT,PAGE_READWRITE ; выделяем память test eax,eax ; в случае ошибки в eax будет ноль, поэтому провряем eax jz aerror ; если не получилось выделить память переходим к сообщению об ошибке mov [f.pointer],eax ; если всё ноормально, то сохраняем указатель на область выделеной памяти в [f.pointer] ; читаем из файла в память invoke ReadFile,edi,[f.pointer],[f.size],bytescount,0 ; ну тут edi - указатель на файл, ; [f.pointer] - указатель на область памяти (в которую читаем) ; [f.size] - размер файла ; два последних параметра: указатель на переменную (dword) и 0 (не берите в голову их предназначение) test eax,eax ; провряем eax jz oerror ; если 0, то прыгаем на сообщени об ошибке invoke CloseHandle,edi ; закрываем файл, он нам больше не понадобится ;; определяем кол-во строк в файле mov esi,[f.pointer] ; в esi область памяти с прочтённым в неё файлом countbn 0Ah ; с помощью макроса считаем сколько в файле переводов строки (0Ah - перевод строки по ASCII) dec cl ; кол-во переводов строки - 1 = кол-во строк (последняя не считается - см. текстовый файл) mov [f.strings],cl ; сохраням в [f.strings] ;############################################################### ###########################; ;####################################### диалоговое окно ###########################################; invoke GetModuleHandle,0 ; получаем хендл test eax,eax ; если не получается получить хендл - то jz herror ; прыгаем на сообщени об ошибке invoke DialogBoxParam,eax,IDD_DLG,HWND_DESKTOP,DialogProc,0 ; создаем диалоговое окно ; eax - хендл ; IDD_DLG - ресурсы ; владелец (рабочий стол) ; процедура окна ; пеpедается в паpаметpе lParam сообщения WM_INITDIALOG (мы ничё не передаём - 0) jmp exit ; переходим на выход из программы herror: ;| invoke MessageBox,NULL,sherror,NULL,MB_ICONERROR+MB_OK ;| jmp exit ;| aerror: ;| сообщения об ошибках invoke MessageBox,NULL,saerror,NULL,MB_ICONERROR+MB_OK ;| jmp exit ;| oerror: ;| invoke MessageBox,NULL,soerror,NULL,MB_ICONERROR+MB_OK ;| exit: invoke ExitProcess,0 ; выход из программы ;############################################################### ###########################; ;###################### процедура диалогового окна ########################################; proc DialogProc hwnddlg,msg,wparam,lparam push ebx esi edi cmp [msg],WM_INITDIALOG je .wminitdialog cmp [msg],WM_COMMAND je .wmcommand cmp [msg],WM_CLOSE je .wmclose xor eax,eax jmp .finish ; инициализация окна .wminitdialog: xor ax,ax ; обнуляем ax mov al,[f.strings] ; в al помещаем число строк (из [f.strings]) mov edx,sscores+14 ; в edx помещаем указатель на замещаемые символы в строке (3 шт. по убыванию) call toASCII ; вызываем функцию toASCII (см. внизу секции кода) invoke SetDlgItemText,[hwnddlg],IDS_SCORES,sscores ; замена текста IDS_SCORES mov esi,[f.pointer] ; указатель на файл в esi mov [f.pointerpos],esi ; указатель в f.pointerpos - позиция указателя readbsn f.description,'/',.ieof ; записываем описание mov [f.pointerpos],esi ; сохраняем текущую позицию указателя invoke SetDlgItemText,[hwnddlg],IDS_DESCRIPTION,f.description ; записываем текст описания IDS_DESCRIPTION jmp .processed ; на метку .processed ; поступление команды .wmcommand: cmp [wparam],BN_CLICKED shl 16 + IDB_RESET ; если команда - нажатие кнопки IDB_RESET je .bcreset ; то переходим на .bcreset cmp [wparam],BN_CLICKED shl 16 + IDB_NEXT ; если команда - не нажатие IDB_NEXT jne .processed ; то её не обрабатываем ; а вот если нажатие кнопки IDB_NEXT cmp [last],1 ; пироверяем не последняя ли строка je .ieof ; если последняя - на .ieof sevennull ; обнуляем строки (макросом) mov esi,[f.pointerpos] ; позицию указателя в esi readbsn f.first,'/',.ieof ; записываем первую форму из файла readbsn f.second,'/',.ieof ; записываем вторую форму из файла readbsn f.third,0Ah,.ieof ; записываем третью форму из файла mov [f.pointerpos],esi ; сохраняем текущую позицию указателя invoke GetDlgItemText,[hwnddlg],IDE_FIRST,first,19 ;| invoke GetDlgItemText,[hwnddlg],IDE_SECOND,second,19 ;| берём введённый текст из editBox'ов invoke GetDlgItemText,[hwnddlg],IDE_THIRD,third,19 ;| ;******************************************************************** ;;сравнение строк mov esi,first ; с поощью макроса cmpstr mov edi,f.first ; сравниваем введённое слово со словом в файле, если не совпадает, то переходим на указаную метку cmptstr .cffalse invoke SetDlgItemText,[hwnddlg],IDS_FIRST,strue ; заисываем в строку "true" inc [f.true] ; увеличиваем количество правильных jmp .cfend .cffalse: invoke SetDlgItemText,[hwnddlg],IDS_FIRST,sfalse ; заисываем в строку "false" inc [f.false] ; увеличиваем количество неправильных .cfend: ;******************************************************************** ; повторяем то же самое для second и third mov esi,second mov edi,f.second cmptstr .csfalse invoke SetDlgItemText,[hwnddlg],IDS_SECOND,strue ; заисываем в строку "true" inc [f.true] jmp .csend .csfalse: invoke SetDlgItemText,[hwnddlg],IDS_SECOND,sfalse ; заисываем в строку "false" inc [f.false] .csend: mov esi,third mov edi,f.third cmptstr .ctfalse invoke SetDlgItemText,[hwnddlg],IDS_THIRD,strue ; заисываем в строку "true" inc [f.true] jmp .ctend .ctfalse: invoke SetDlgItemText,[hwnddlg],IDS_THIRD,sfalse ; заисываем в строку "false" inc [f.false] .ctend: mov esi,[f.pointerpos] ; в esi помещаем текущую позицию указателя [f.pointerpos] readbsn f.description,'/',.ieof ; записываем описание (уже следующего глагола) jmp .next ; если записывать нечего (конец файла), то макрос переведёт нас на метку .ieof, а так обходим её стороной .ieof: ; конец файла cmp [last],1 ; сравниваем с 1 jne @f ; если не равно - прыгаем на ближайшую последущую анонимную метку invoke MessageBox,[hwnddlg],slast,NULL,MB_ICONERROR+MB_OK ; если равно - выводим сообщение о конце файла @@: ; если не равно mov [last],1 ; записываем в [last] 1 (для последующего нажатия кнопки next) dec [f.done] ; сделаных + 1 .next: mov [f.pointerpos],esi ; сохраняем текущую позицию указателя invoke SetDlgItemText,[hwnddlg],IDS_DESCRIPTION,f.description ; записываем описание следующего глагола inc [f.done] ; сделаные + 1 ; переводим в десятичные числа с помощью функции toASCII xor ax,ax ; сделаные mov al,[f.done] mov edx,sscores+10 call toASCII xor ax,ax ; правильные mov ax,[f.true] mov edx,sscores+31 call toASCII xor ax,ax mov ax,[f.false] ; неправильные mov edx,sscores+35 call toASCII invoke SetDlgItemText,[hwnddlg],IDS_SCORES,sscores ; переписываем IDS_SCORES jmp .processed .bcreset: ; нажатие кнопки reset mov [last],0 ; обнуляем [last] mov [f.true],0 ; обнуляем [f.true] mov [f.false],0 ; обнуляем [f.false] mov [f.done],0 ; обнуляем [f.done] xor ax,ax ;| mov al,[f.done] ;| mov edx,sscores+10 ;| call toASCII ;| xor ax,ax ;| mov ax,[f.true] ;| переводим обнулённые переменные в десятичный формат mov edx,sscores+31 ;| call toASCII ;| xor ax,ax ;| mov ax,[f.false] ;| mov edx,sscores+35 ;| call toASCII ;| invoke SetDlgItemText,[hwnddlg],IDS_SCORES,sscores ; переписываем IDS_SCORES mov ecx,215 ; @@: ; mov byte [f.description+ecx],0 ; обнуляем [f.description] loop @b ; invoke SetDlgItemText,[hwnddlg],IDS_DESCRIPTION,f.description ; записываем в IDS_DESCRIPTION пустую строку ; invoke SetDlgItemText,[hwnddlg],IDS_FIRST,snull ; выставляем в ноль IDS_FIRST invoke SetDlgItemText,[hwnddlg],IDS_SECOND,snull ; -"- IDS_SECOND invoke SetDlgItemText,[hwnddlg],IDS_THIRD,snull ; -"- IDS_THIRD - там теперь пустые строки jmp .wminitdialog ; переходим на .wminitdialog .wmclose: ; сообщение о закрытие окна invoke EndDialog,[hwnddlg],0 ; закрытие окна .processed: ; продолжение работы диалогового окна mov eax,1 ; записываем в eax 1, если записать 0, то окно завершится .finish: pop edi esi ebx ret endp ;;@ функция, преобразует двоичное число в десятичное (не более трёхзначного) toASCII: ;; в ax двоичное число (ah - пусто, al - байт) ;; в edx указатель на строку данных -1, в которую записываем результат mov bl,10 ; в bl делитель -> 10 mov ecx,3 ; в ecx число повторения цикла @@: div bl ; частное -> al,остаток -> ah or ah,30h ; прибавляем к остатку 30h: 0 - 30h, 9 - 39h по таблице ASCII mov byte [edx+ecx],ah ; ппомещаем ASCII результат в память с адресом в edx xor ah,ah ; обнуляем ah loop @b ; цикл пока cx не ноль ret ; возврат ;;@ ; импортные данные как обычно ; в fasm 1.67.26 можно не перечислять все функции, а просто написать ; ; section '.idata' import data readable writeable ; ; library kernel32,'KERNEL32.DLL',\ ; user32,'USER32.DLL',\ ; gdi32,'GDI32.DLL' ; ; include 'api\kernel32.inc' ; include 'api\user32.inc' ; include 'api\gdi32.inc' ; section '.idata' import data readable writeable library kernel,'KERNEL32.DLL',\ user,'USER32.DLL' import kernel,\ GetModuleHandle,'GetModuleHandleW',\ ExitProcess,'ExitProcess',\ CreateFile,'CreateFileA',\ VirtualAlloc,'VirtualAlloc',\ ReadFile,'ReadFile',\ GetFileSize,'GetFileSize',\ CloseHandle,'CloseHandle' import user,\ DialogBoxParam,'DialogBoxParamA',\ CheckRadioButton,'CheckRadioButton',\ GetDlgItemText,'GetDlgItemTextA',\ SetDlgItemText,'SetDlgItemTextA',\ IsDlgButtonChecked,'IsDlgButtonChecked',\ MessageBox,'MessageBoxA',\ EndDialog,'EndDialog' ; ресурсы, надеюсь тут всё понятно section '.rsrc' resource data readable directory RT_DIALOG,dialogs,\ RT_ICON,icons,\ RT_GROUP_ICON,group_icons,\ RT_VERSION,versions resource dialogs,\ IDD_DLG,LANG_RUSSIAN,demonstration dialog demonstration,'Irregverbs-s v0.0a /121',70,70,190,175,WS_CAPTION+WS_POPUP+WS_SYSMENU+DS_MODALFRAME+WS_MINIMIZEBOX dialogitem 'STATIC','&Description',-1,10,5,70,80,WS_VISIBLE dialogitem 'STATIC','..',IDS_DESCRIPTION,10,15,180,40,WS_VISIBLE ; dialogitem 'STATIC','&First:',-1,10,60,70,8,WS_VISIBLE dialogitem 'EDIT','',IDE_FIRST,10,70,150,13,WS_VISIBLE+WS_BORDER+WS_TABSTOP dialogitem 'STATIC','----',IDS_FIRST,165,70,20,10,WS_VISIBLE ; dialogitem 'STATIC','&Second:',-1,10,90,70,8,WS_VISIBLE dialogitem 'EDIT','',IDE_SECOND,10,100,150,13,WS_VISIBLE+WS_BORDER+WS_TABSTOP dialogitem 'STATIC','----',IDS_SECOND,165,100,20,10,WS_VISIBLE ; dialogitem 'STATIC','&Third:',-1,10,120,70,8,WS_VISIBLE dialogitem 'EDIT','',IDE_THIRD,10,130,150,13,WS_VISIBLE+WS_BORDER+WS_TABSTOP dialogitem 'STATIC','----',IDS_THIRD,165,130,20,10,WS_VISIBLE ; dialogitem 'STATIC','&Scores',-1,10,145,70,8,WS_VISIBLE dialogitem 'STATIC','done/all = 0/178 true/false = 0/34',IDS_SCORES,10,155,70,80,WS_VISIBLE ; dialogitem 'BUTTON','next >>',IDB_NEXT,85,150,45,15,WS_VISIBLE+WS_TABSTOP+BS_DEFPUSHBUTTON dialogitem 'BUTTON','reset',IDB_RESET,135,150,45,15,WS_VISIBLE+WS_TABSTOP+BS_PUSHBUTTON enddialog resource icons,\ 1,LANG_NEUTRAL,icon_data resource group_icons,\ 17,LANG_NEUTRAL,main_icon resource versions,\ 1,LANG_NEUTRAL,version icon main_icon,icon_data,'minipad.ico' versioninfo version,VOS__WINDOWS32,VFT_APP,VFT2_UNKNOWN,LANG_ENGLISH+SUBLANG_DEFAULT,0,\ 'FileDescription','Irregverbs',\ 'LegalCopyright','No rights reserved.',\ 'FileVersion','0.0a',\ 'ProductVersion','0.0a-121',\ 'PlatformVersion','0.0a',\ 'InterfaceVersion','0.0a',\ 'OriginalFilename','IRREGVERBS-S.EXE' |
|
|---|