Содержание:
- Глава 1 - предисловие и материалы для скачивания
- Глава 2 - предварительные сведения перед изучением ассемблера
- Глава 3 - архитектура процессора 8086
- Глава 4 - сегментация, стэк, прерывания, адресация
- Глава 5 - ассемблер (директивы и операторы)
- Глава 6 - ассемблер (выражения, приоритеты и ссылки вперёд)
- Глава 7 - Загрузка и выполнение программ в DOS, структура EXE и COM программ
- Глава 8 - команды процессора: пересылка данных, стэк, ввод/вывод
- Глава 9 - арифметические команды процессора
- Глава 10 - команды операций сдвигов в Ассемблере
- Глава 11 - команды сравнения и передачи управления в Ассемблере
- Глава 12 - подпрограммы и прерывания в Ассемблере
- Глава 13 - строковые команды в Ассемблере
- Глава 14 - управление процессором
- Глава 15 - практика:EXE и COM программы, вывод на экран
- Глава 16 - практика: циклы и ввод с клавиатуры
- Глава 17 - практика: ввод чисел и системы счисления
- Глава 18 - практика: работа с файлами, перехват и восстановление прерываний
- Глава 19 - практика: дополнительные сведения
- Глава 20 - программирование для Windows
ВНИМАНИЕ! Данный самоучитель был написан много лет назад и его автор не сможет ответить на ваши вопросы. Курс по assembler предназначен для саморазвития. Если у вас хватает квалификации, можете предложить внести правки.
Рассмотрим задачу создания текстового редактора. Программировать на ассемблере под Windows очень просто. Надо лишь функции вызывать. Вообще говоря конечно тут всё не так просто про программирование под Windows на ассемблере можно создать целую книгу. Она конечно будет содержать описания WinAPI! поэтому если что то не ясно то смотрите дополнительный материал.
Для начала рассмотрим ка это делать на Masm 8.0! Версия именно такая!
Для создания программы использовался инструмент MASM32 Prostart Code Wizard, который сгенерировал основной каркас программы – файл ресурса с меню (File, Help) и иконкой, основной файл программы содержащий стандартный каркас приложения – создания окна, обработка основных сообщений, файл с описанием функций стандартных диалоговых окон по открытию и сохранению файлов, включаемый файл содержащий описание необходимых данных, make файл позволяющий проводить компиляцию и сборку приложения. Для создания простейшего текстового редактора в процессе обработки сообщения WM_CREATE создается текстовое поле – окно с преопределенным классом EDIT, с помощью функции CreateWindowEx. Для организации открытия и сохранения файла в процессе обработки сообщения WM_COMMAND проверяется какой пункт меню выбран и в зависимости от этого предпринимается либо вызов функции открытия файла либо его сохранения с целью получения полного имени файла. Далее при открытии с помощь CreateFile создается файл, выделяется и блокируется память для буфера GlobalAlloc и GlobalLock, файл читается в буфер ReadFile, окну редактора посылается сообщение WM_SETTEXT, выделенная память освобождается GlobalUnLock и GlobalFree. При сохранении последовательность действий та же но окну посылается сообщение WM_GETTEXT а вместо ReadFile используется WriteFile. Обрабатываются также сообщения WM_SIZE – для изменения размера окна редактора и сообщение WM_CLOSE для про-верки модификации текста и сохранения его (опрос окна редактора через SendMessage с сообщением EM_GETMODIFY)
Запустите файл PROSTART.EXE - перед вами удобный генератор исходных текстов программ! Отметьте значки как на рисунке и нажмите Create Project:
После этого создастся проект! Замените файлы на те что приведены здесь:
Project.asm
; ######
.386
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive
include Project.inc ; local includes for this file
; #######
.code
start:
invoke GetModuleHandle, NULL
mov hInstance, eax
invoke GetCommandLine
mov CommandLine, eax
invoke WinMain, hInstance, NULL, CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
; #######
hPrevInst :DWORD,
CmdLine :DWORD,
CmdShow :DWORD
;====================
; Put LOCALs on stack
;====================
LOCAL wc :WNDCLASSEX
LOCAL msg :MSG
LOCAL Wwd :DWORD
LOCAL Wht :DWORD
LOCAL Wtx :DWORD
LOCAL Wty :DWORD
;=====
; Fill WNDCLASSEX structure with required variables
;=====
invoke LoadIcon,hInst,500 ; icon ID
mov hIcon, eax
szText szClassName,"Project_Class"
mov wc.cbSize, sizeof WNDCLASSEX
mov wc.style, CS_BYTEALIGNWINDOW
mov wc.lpfnWndProc, offset WndProc
mov wc.cbClsExtra, NULL
mov wc.cbWndExtra, NULL
m2m wc.hInstance, hInst
mov wc.hbrBackground, COLOR_WINDOW+12
mov wc.lpszMenuName, NULL
mov wc.lpszClassName, offset szClassName
m2m wc.hIcon, hIcon
invoke LoadCursor, NULL, IDC_ARROW
mov wc.hCursor, eax
m2m wc.hIconSm, hIcon
invoke RegisterClassEx, ADDR wc
;======
; Centre window at following size
;======
mov Wwd, 500
mov Wht, 350
invoke GetSystemMetrics, SM_CXSCREEN
invoke TopXY,Wwd,eax
mov Wtx, eax
invoke GetSystemMetrics, SM_CYSCREEN
invoke TopXY, Wht, eax
mov Wty, eax
invoke CreateWindowEx,WS_EX_LEFT,
ADDR szClassName,
ADDR szDisplayName,
WS_OVERLAPPEDWINDOW,
Wtx,Wty,Wwd,Wht,
NULL, NULL,
hInst, NULL
mov hWnd,eax
invoke LoadMenu, hInst,600 ; menu ID
invoke SetMenu, hWnd, eax
invoke ShowWindow, hWnd, SW_SHOWNORMAL
invoke UpdateWindow, hWnd
;======
; Loop until PostQuitMessage is sent
;======
StartLoop:
invoke GetMessage,ADDR msg, NULL,0,0
cmp eax, 0
je ExitLoop
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
jmp StartLoop
ExitLoop:
return msg.wParam
WinMain endp
; #####
WndProc proc hWin :DWORD,
uMsg :DWORD,
wParam :DWORD,
lParam :DWORD
LOCAL var :DWORD
LOCAL caW :DWORD
LOCAL caH :DWORD
LOCAL Rct :RECT
LOCAL hDC :DWORD
LOCAL Ps :PAINTSTRUCT
LOCAL buffer1[128]:BYTE ; these are two spare buffers
LOCAL buffer2[128]:BYTE ; for text manipulation etc..
.if uMsg == WM_COMMAND
;== menu commands ==
.if wParam == 1000
jmp @F
szTitleO db "Открыть файл",0
szFilterO db "All files",0,"*.*",0,
"Text files",0,"*.txt",0,0
@@:
invoke FillBuffer, ADDR szFileName, length szFileName,0
invoke GetFileName, hWin, ADDR szTitleO, ADDR szFilterO
cmp szFileName[0],0 ;<< zero if cancel pressed in dlgbox
je @F
; file name returned in szFileName
invoke CreateFile, ADDR szFileName, GENERIC_READ or GENERIC_WRITE ,\
FILE_SHARE_READ or FILE_SHARE_WRITE,\
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE,\
NULL
mov hFile,eax
;Выделение динамической памяти и сохранение дескриптора
invoke GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, MEMSIZE
mov hMemory,eax
;Закрытие блока памяти и сохранение указателя на него
invoke GlobalLock, hMemory
mov pMemory,eax
;Чтение файла
invoke ReadFile,hFile,pMemory,MEMSIZE-1,\
ADDR SizeReadWrite, NULL
;Смена текста в EDIT
invoke SendMessage, hwndEdit, WM_SETTEXT, NULL, pMemory
;Закрытие файла
invoke CloseHandle,hFile
;Открытие блока памяти и его освобождение
invoke GlobalUnlock, pMemory
invoke GlobalFree, hMemory
@@:
.elseif wParam == 1001
jmp @F
szTitleS db "Сохранить файл",0
szFilterS db "All files",0,"*.*",0,
"Text files",0,"*.txt",0,0
@@:
s:
invoke FillBuffer, ADDR szFileName, length szFileName,0
invoke SaveFileName,hWin,ADDR szTitleS,ADDR szFilterS
cmp szFileName[0],0 ;<< zero if cancel pressed in dlgbox
je @F
; file name returned in szFileName
;Открытие файла и сохранение его дескриптора
invoke CreateFile,ADDR szFileName,GENERIC_READ or GENERIC_WRITE ,\
FILE_SHARE_READ or FILE_SHARE_WRITE,\
NULL, CREATE_NEW, FILE_ATTRIBUTE_ARCHIVE,\
NULL
mov hFile,eax
;Выделение динамической памяти и сохранение дескриптора
invoke GlobalAlloc, GMEM_MOVEABLE or GMEM_ZEROINIT, MEMSIZE
mov hMemory,eax
;Закрытие блока памяти и сохранение указателя на него
invoke GlobalLock,hMemory
mov pMemory,eax
;Получение текста из EDIT
invoke SendMessage, hwndEdit, WM_GETTEXT, MEMSIZE-1,pMemory
;Запись в файл и его закрытие
invoke WriteFile, hFile, pMemory, eax, ADDR SizeReadWrite, NULL
invoke CloseHandle,hFile
;Открытие блока памяти и его освобождение
invoke GlobalUnlock,pMemory
invoke GlobalFree,hMemory
@@:
.endif
.if wParam == 1010
invoke SendMessage, hWin, WM_SYSCOMMAND, SC_CLOSE,NULL
.elseif wParam == 1900
szText AboutMsg, "Программа - текстовый редактор", 13, 10, "Copyright © Student IS-103 2004"
invoke ShellAbout, hWin, ADDR szDisplayName, ADDR AboutMsg, hIcon
.endif
;====== end menu commands ======
.elseif uMsg == WM_CREATE
szText EditClass,"EDIT"
invoke CreateWindowEx, NULL, ADDR EditClass, NULL, WS_VISIBLE or WS_CHILD or ES_LEFT or ES_MULTILINE or\
ES_AUTOVSCROLL, 5, 5, 475, 280, hWin, 1111, hInstance, NULL
mov hwndEdit,eax
invoke SetFocus,hwndEdit
.elseif uMsg == WM_SIZE
invoke GetClientRect,hWin, ADDR Rct
sub Rct.right,10
sub Rct.bottom,10
invoke MoveWindow, hwndEdit, 5, 5, Rct.right, Rct.bottom,1
.elseif uMsg == WM_PAINT
invoke BeginPaint,hWin,ADDR Ps
mov hDC, eax
invoke Paint_Proc,hWin,hDC
invoke EndPaint, hWin, ADDR Ps
return 0
.elseif uMsg == WM_CLOSE
szText TheText,"Текст не сохранен - Сохранить?"
invoke SendMessage, hwndEdit, EM_GETMODIFY,0,0
test eax,eax
jz nomod
invoke MessageBox,hWin,ADDR TheText,ADDR szDisplayName,MB_YESNOCANCEL
.if eax == IDYES
jmp s ;return 0
.endif
.if eax == IDCANCEL
return 0
.endif
.if eax == IDNO
jmp nomod
.endif
.elseif uMsg == WM_DESTROY
nomod: invoke PostQuitMessage,NULL
return 0
.endif
invoke DefWindowProc, hWin, uMsg, wParam, lParam
ret
WndProc endp
; ######
TopXY proc wDim:DWORD, sDim:DWORD
shr sDim, 1 ; divide screen dimension by 2
shr wDim, 1 ; divide window dimension by 2
mov eax, wDim ; copy window dimension into eax
sub sDim, eax ; sub half win dimension from half screen dimension
return sDim
TopXY endp
; ######
Paint_Proc proc hWin:DWORD, hDC:DWORD
LOCAL btn_hi :DWORD
LOCAL btn_lo :DWORD
LOCAL Rct :RECT
invoke GetSysColor, COLOR_BTNHIGHLIGHT
mov btn_hi, eax
invoke GetSysColor, COLOR_BTNSHADOW
mov btn_lo, eax
return 0
Paint_Proc endp
; #######
end start
Файл filedlgs.asm
; ########
GetFileName PROTO :DWORD, :DWORD, :DWORD
SaveFileName PROTO :DWORD, :DWORD, :DWORD
FillBuffer PROTO :DWORD, :DWORD, :BYTE
.data
szFileName db 260 dup(0)
ofn OPENFILENAME <> ; structure
.code
; #######
GetFileName proc hParent:DWORD, lpTitle:DWORD, lpFilter:DWORD
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, hParent
m2m ofn.hInstance, hInstance
m2m ofn.lpstrFilter, lpFilter
m2m ofn.lpstrFile, offset szFileName
mov ofn.nMaxFile, sizeof szFileName
m2m ofn.lpstrTitle, lpTitle
mov ofn.Flags, OFN_EXPLORER or OFN_FILEMUSTEXIST or \
OFN_LONGNAMES
invoke GetOpenFileName,ADDR ofn
ret
GetFileName endp
; ######
SaveFileName proc hParent:DWORD, lpTitle:DWORD, lpFilter:DWORD
mov ofn.lStructSize, sizeof OPENFILENAME
m2m ofn.hWndOwner, hParent
m2m ofn.hInstance, hInstance
m2m ofn.lpstrFilter, lpFilter
m2m ofn.lpstrFile, offset szFileName
mov ofn.nMaxFile, sizeof szFileName
m2m ofn.lpstrTitle, lpTitle
mov ofn.Flags, OFN_EXPLORER or OFN_LONGNAMES
invoke GetSaveFileName,ADDR ofn
ret
SaveFileName endp
; #####
FillBuffer proc lpBuffer:DWORD, lenBuffer:DWORD, TheChar:BYTE
push edi
mov edi, lpBuffer ; address of buffer
mov ecx, lenBuffer ; buffer length
mov al, TheChar ; load al with character
rep stosb ; write character to buffer until ecx = 0
pop edi
ret
FillBuffer endp
; ####
Файл Project.inc
; ####
; include files
; ~~~~~~~~~~~~~
include C:\MASM32\INCLUDE\windows.inc
include C:\MASM32\INCLUDE\masm32.inc
include C:\MASM32\INCLUDE\gdi32.inc
include C:\MASM32\INCLUDE\user32.inc
include C:\MASM32\INCLUDE\kernel32.inc
include C:\MASM32\INCLUDE\Comctl32.inc
include C:\MASM32\INCLUDE\comdlg32.inc
include C:\MASM32\INCLUDE\shell32.inc
; libraries
; ~~~~~~~~~
includelib C:\MASM32\LIB\masm32.lib
includelib C:\MASM32\LIB\gdi32.lib
includelib C:\MASM32\LIB\user32.lib
includelib C:\MASM32\LIB\kernel32.lib
includelib C:\MASM32\LIB\Comctl32.lib
includelib C:\MASM32\LIB\comdlg32.lib
includelib C:\MASM32\LIB\shell32.lib
; ###
;======
; Local prototypes
;=====
WinMain PROTO :DWORD,:DWORD,:DWORD,:DWORD
WndProc PROTO :DWORD,:DWORD,:DWORD,:DWORD
TopXY PROTO :DWORD,:DWORD
FillBuffer PROTO :DWORD, :DWORD, :BYTE
Paint_Proc PROTO :DWORD,:DWORD
wsprintfA PROTO C :DWORD,:VARARG
wsprintf equ
;=====
; Local macros
;=====
szText MACRO Name, Text:VARARG
LOCAL lbl
jmp lbl
Name db Text,0
lbl:
ENDM
m2m MACRO M1, M2
push M2
pop M1
ENDM
return MACRO arg
mov eax, arg
ret
ENDM
MAXSIZE equ 260
MEMSIZE equ 65535
.data
szDisplayName db "Text Editor",0
CommandLine dd 0
hWnd dd 0
hInstance dd 0
hIcon dd 0
.data?
hwndEdit HWND ?
hFile HANDLE ?
hMemory HANDLE ?
pMemory DWORD ?
SizeReadWrite DWORD ?
; ## Inserted modules ##
include filedlgs.asm
; #####
Файл rsrc.rc
500 ICON MOVEABLE PURE LOADONCALL DISCARDABLE "PROJECT.ICO"
600 MENUEX MOVEABLE IMPURE LOADONCALL DISCARDABLE
BEGIN
POPUP "&File", , , 0
BEGIN
MENUITEM "&Open", 1000
MENUITEM "", , 0x0800 /*MFT_SEPARATOR*/
MENUITEM "&Save", 1001
MENUITEM "", , 0x0800 /*MFT_SEPARATOR*/
MENUITEM "&Exit", 1010
END
POPUP "&Help", , , 0
BEGIN
MENUITEM "&About", 1900
END
END
Компиляция makeit.bat - он сгенерирован автоматически
Результат: