Партнерка на США и Канаду по недвижимости, выплаты в крипто

  • 30% recurring commission
  • Выплаты в USDT
  • Вывод каждую неделю
  • Комиссия до 5 лет за каждого referral

LINK [опции] [файлы] [@commandfile]

/DEBUG

Отладка

Это создаст информацию для отладки. Используйте эту опцию, когда вы хотите использовать отладчик.

/DEBUGTYPE:CV|COFF

Тип отладки: codeview / coff

Выбирает выходной формат отладочной информации. Это зависит от вашего отладчика. Softice и visual c++ отладчики оба могут обрабатывать CV (codeview)

/DEF:имя_файла

DEF файл

Указывает файл определения (.def). Используется с dll, для экспортируемых функций.

/DLL

DLL

Выходной файл DLL, а не EXE.

/LIBPATH:path

Путь к библиотекам

Указывает путь к файлам библиотек (*.lib).

/I<имя>

Устанавливает путь для inc-файлов

Указывает путь для inc-файлов, по умолчанию.

/OUT:имя_файла

Out:имя_файла

Может изменить имя выходного файла.

/SUBSYSTEM:{...}

Подсистема

Выбирает ОС на которой должна выполнятся программа: NATIVE|WINDOWS|CONSOLE|WINDOWSCE|POSIX

Я установил masm в папку d:\masm\masm32, в папке d:\masm находятся все тексты наших программ *.asm. А для компиляции я создал bat файл, который компилирует файл current. asm:

;======[CUT HERE]=====

d:\masm\masm32\bin\ml. exe /c /coff current. asm

d:\masm\masm32\bin\link. exe /subsystem:windows current. obj

pause

;=======[CUT HERE]========

В результате после запуска это файл у нас в папке d:\masm готовая скомпилированная программа current. exe.

Вот и конец этого урока. В этом уроке я рассказал про макрософтский компилятор MASM. На следующем уроке мы напишем первое оконное приложение на ассемблере.

НЕ нашли? Не то? Что вы ищете?

Урок 14

На этом уроке мы напишем оконное приложение на ассемблере. Я буду писать его на MASM. Это приложение я постарался сделать наиболее минимальным и понятным.

.386p

.model flat, stdcall

option casemap:none

includelib.\masm32\lib\kernel32.lib

includelib.\masm32\lib\user32.lib

include.\masm32\include\windows. inc

include.\masm32\include\kernel32.inc

include.\masm32\include\user32.inc

.data

newhwnd dd 0

hInst dd h

szTitleName db 'Window Application',0

szClassName db 'ASMCLASS32',0

msg MONMSGSTRUCT <?> ; структура сообщения

wc WNDCLASS <?> ; структура класса

.code

start:

Invoke GetModuleHandle,0 ; получаем hInstanse

Mov [hInst], eax

Mov [wc. style], CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS

; устанавливаем стиль окна

Mov [wc. lpfnWndProc], offset WndProc ;

Mov [wc. cbClsExtra], 0

Mov [wc. cbWndExtra], 0

Mov eax, [hInst]

Mov [wc. hInstance], eax

Invoke LoadIcon,0,IDI_APPLICATION ; получаем значок приложения по

; умолчанию

Mov [wc. hIcon], eax

Invoke LoadCursorA,0,IDC_ARROW ; получаем курсор по умолчанию

Mov [wc. hCursor], eax

Mov [wc. hbrBackground], COLOR_BACKGROUND+1

Mov dword ptr [wc. lpszMenuName], 0

Mov dword ptr [wc. lpszClassName], offset szClassName ; задаём имя класса

;окна

Invoke RegisterClassA, offset wc ; регистрируем класс окна

Push 0

Push [hInst] ; дескриптор

Push 0

Push 0

Push CW_USEDEFAULT ; высота

Push CW_USEDEFAULT ; ширина

Push CW_USEDEFAULT ; y

Push CW_USEDEFAULT ; x

Push WS_OVERLAPPEDWINDOW ; стиль

Push offset szTitleName ; заголовок окна

Push offset szClassName ; имя класса

Push 0 ; дополнительный стиль

Call CreateWindowEx ; создаём окно

mov [newhwnd], eax ; сохраняем его дескриптор

invoke ShowWindow,[newhwnd],SW_SHOWNORMAL; показываем окно

invoke UpdateWindow, [newhwnd]; обновляем его

msg_loop: ; запускаем цикл обработки сообщений

invoke GetMessage, offset msg, 0,0,0

cmp ax, 0

je end_loop

invoke TranslateMessage, offset msg

invoke DispatchMessage, offset msg

jmp msg_loop

end_loop:

invoke ExitProcess, 0

WndProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD

Cmp [wmsg], WM_DESTROY

Je wmdestroy

Cmp [wmsg], WM_KEYDOWN

Je wmkeydown

Invoke DefWindowProcA,[hwnd],[wmsg],[wparam],[lparam]

; вызываем стандартный обработчик сообщений

Jmp finish

wmkeydown:

cmp [wparam], VK_ESCAPE

je wmdestroy; если нажата клавиша Escape то выход

jmp finish

wmdestroy:

invoke PostQuitMessage, 0

invoke ExitProcess, 0 ; выход

finish:

ret

WndProc endp

end start

В самой первой строке мы получаем hInstanse т. е хендл приложения, фактически это база образа приложения, т. е. то место в памяти в которого начинается наша программа. Не пойму, зачем именно это нужно, но это зачем-то нужно. Функция GetModuleHandle нужна для получения хендла библиотеки (фактически хендл библиотеки это и есть её база образа), параметром этой функции надо передавать имя библиотеки, но если мы укажем 0, то получим хендл нашего приложения. Потом мы заполняем структуру класса окна, т. е. задаём атрибуты класса окна.

Mov [wc. lpfnWndProc], offset WndProc

Этой строкой мы указываем, какая функция будет обрабатывать сообщения окна. Функция, которая обрабатывает сообщения окна, называется оконной функцией. Оконная функция вызывается всякий раз, когда окну было прислано какое-либо сообщение.

Потом мы получаем иконку окна с помощью функции LoadIcon, в качестве первого параметра этой функции надо передавать хендл приложения, но мы указали 0 поэтому мы получим стандартный значок окна. Во втором параметре мы указываем указатель строку, которая содержит имя иконки, которую мы хотим получить, но если мы укажем определённую константу, то сможем получить предопределённую иконку. Точно также мы получаем курсор, т. е. его хендл.

Потом мы вызываем RegisterClass, единственным параметром которой является указатель на структуру, которая описывает новый класс окна.

Потом мы создаём окно с помощью функции CreateWindowEx.

HWND CreateWindowEx(

DWORD dwExStyle, // расширенный стиль окна

LPCTSTR lpClassName, // имя класса

LPCTSTR lpWindowName, // заголовок окна

DWORD dwStyle, // стиль окна

int x, // позиция х

int y, // позиция у

int nWidth, // ширина

int nHeight, // высота

HWND hWndParent, // хендл окна родителя

HMENU hMenu, // хендл меню

HINSTANCE hInstance, // хендл приложения

LPVOID lpParam //указатель на данные (обычно они не нужны)

);

После создания окна мы показываем его и обновляем. Потом запускаем бесконечный цикл обработки системных сообщений.

В оконной функции мы получаем сообщение и обрабатываем его. Если тип сообщения WM_DESTROY, то мы прыгаем на соответствующую метку, после которой вы выходим из нашей программы. Если была нажата клавиша, то мы продолжаем обработку и смотрим, нажата ли клавиша escape, если да, то выходим. Если сообщение, какое либо другое, то вызываем стандартный обработчик сообщений окна. Этот обработчик превращает наше окно в настоящее "живое" окно, которое может двигаться, расширятся и свёртываться. Можно и не вызывать эту функцию, но для того чтобы окно стало живым нам придётся вручную обрабатывать все сообщения окна, а это просто нецелесообразно.

Вот и написали мы оконное приложение. Мне кажется для первого раза это не слишком трудно. Надеюсь, этот урок был не слишком скучным.

Урок 15

Функции для Win-32

На прошлом уроке мы написали первое оконное приложение на ассемблере. На прошлом уроке я вам рассказал структуру ЛЮБОГО оконного приложения. Сегодня я вам расскажу (т. е. опишу) несколько функций API для работы с памятью.

Как я вам уже рассказывал, в Win32 есть только API функции. ЛЮБОЕ приложение в ЛЮБОМ случае должно использовать АПИ функции (по крайней мере, для того чтобы оно могло нормально завершиться). Эти функции находятся в библиотеках kernel32.dll, user32.dll, gdi32.dll (3 классические библиотеки) и др. Функции библиотеки kernel32.dll самые главные, они отвечают за работу с файлами памятью, от них никуда не денешься, user32.dll отвечает за окна и интерфейс пользователя, а gdi32.dll за "рисование" и мультимедиа. Для того, что бы использовать функции этих библиотек надо сначала их загрузить (kernel32.dll загружать не надо).

Каждое приложение проецируется в своё собственное виртуальное адресное пространство размером в 4 ГБ, верхние 2 из которых недоступны для него. Это пространство (вернее нижние 2 ГБ) подготавливается для него: в него загружаются 2 библиотеки kernel32.dll и ntdll. dll (для Win NT) всегда по одинаковым адресам, подготавливается стек для главной нити процесса и ещё много чего. В эту память загружаются код и данные приложения. Для того, что бы операционная система знала по каким адресам надо загружать данные и код приложения она смотрит дополнительную информацию о секциях приложения в "экзе" файле. Если она этого не сделает, то она просто не будет знать, куда спроецировать код и данные, следовательно, все обращения к памяти будут неверными. (Мы, конечно, помним что под записью mov eax, [value] понимается помещение в регистр eax содержимого некого адреса памяти, которую подразумевает метка value, эта метка подразумевает некий фиксированный адрес, все адреса рассчитываются при компиляции программы и вам об этом задумываться не надо).

Каждое приложение в своей работе вызывает API функции, под вызовом функции подразумевается передача управления некоторому адресу, который находится в диапазоне памяти, в которую загружена библиотека, которая содержит данную функцию. Рассмотрим пример.

Call VirtualAalloc

Как мы уже знаем слово VirtualAlloc будет заменено на некоторый адрес. Этот адрес будет соответствовать адресу точки входа функции VirtualAlloc. Потом эта функция передаёт управление функциям Native API которые находятся в библиотеке ntdll. dll. Функции Native API подготавливают процесс к переходу в режим ядра и командой sysenter переводят процесс в режим ядра и т. д. Дальше я не буду рассказывать, потому что это слишком много для одного урока.

Теперь я опишу несколько API функций для работы с памятью.

Функция VirtualAlloc позволяет зарезервировать некоторый участок памяти заданного размера, при этом эта память полностью обнуляется.

Вот описание этой функции из MS SDK в оригинале

LPVOID VirtualAlloc(

LPVOID lpAddress, // address of region to reserve or commit

DWORD dwSize, // size of region

DWORD flAllocationType, // type of allocation

DWORD flProtect // type of access protection

);

    lpAddress - начальный адрес региона dwSize - размер региона flAllocationType - тип резервирования может быть указана одна из 3х констант :
      MEM_COMMIT эта память может быть сброшена в файл подкачки MEM_RESERVE этот участок памяти не может быть сброшен в файл подкачки он будет присутствовать в физической памяти всегда, пока эту память процесс не ввысвободит. MEM_TOP_DOWN не пойму для чего нужна эта константа, но она есть, она позволяет зарезервировать виртуальную память, которая будет соответствовать максимально возможному физическому адресу.
    flProtect тип доступа к памяти. Могут быть использованы эти константы или их комбинации.
      PAGE_READONLY PAGE_READWRITE PAGE_EXECUTE позволяет передавать управление этому региону попытка чтения или записи приводит к нарушению прав доступа. PAGE_EXECUTE_READ PAGE_EXECUTE_READWRITE PAGE_NOACCESS

Мне кажется всё и так понятно, кому не понятно читайте MS SDK.

Функция VirtualFree обратна функции VirtualAlloc высвобождает заданный диапазон памяти.

BOOL VirtualFree(

LPVOID lpAddress, // начальный адрес освобождаемого региона

DWORD dwSize, // размер региона

DWORD dwFreeType // type of free operation

);

dwFreeType метод высвобождения:

если укажете MEM_RELEASE то размер указывать не надо, если MEM_DECOMMIT, то размер надо указывать остальных различий, если указано MEM_RELEASE, то эта память высвобождается полностью.

Если функция завершилась нормально, то результат отличен от нуля.

Функция VirtualProtect позволяет изменить тип доступа к зарезервированной памяти, но не так всё просто надо ещё указать старый тип доступа.

BOOL VirtualProtect(

LPVOID lpAddress, // начальный адрес

DWORD dwSize, // размер

DWORD flNewProtect, // новый тип доступа

PDWORD lpflOldProtect // старый тип доступа

);

Вроде всё понятно.

Функция VirtualLock блокирует участок памяти, при этом доступ к нему невозможен и одновременно не приводит к ошибке.

BOOL VirtualLock(

LPVOID lpAddress, // начальный адрес

DWORD dwSize // размер

);

При удачном исходе результат не равен нулю.

Функция VirtualUnlock обратная предыдущей функции.

BOOL VirtualUnlock(

LPVOID lpAddress,

DWORD dwSize

);

При удачном исходе результат не равен нулю.

Все указанные выше функции могут работать только с памятью текущего процесса.

На сегодня хватит. Для этих целей существует MS SDK. Я объяснил только несколько функций.

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5