Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Первая программа

Автор: Руслан Аблязов
6 октября 2006 года

На этом уроке мы с вами напишем первую программу на ассемблере. Но сначала я вам объясню структуру программы на ассемблере. Самая первая программа будет написана на TASM, потому что язык TASM классический, стандартный, без наворотов, а о MASM (макроассемблер) я вам буду говорить на следующих уроках.

Общая структура программы.

	.386p		;тип процессора
	.model flat, stdcall  ; модель памяти и вызова подпрограмм
;объявление включаемых (заголовочных) файлов, макросов, макроопределений, 
; также внешних определений
	.data
; Инициализированные данные
	.data?
; неинициализированные данные
	.const
; константы
	.code
; исполняемый код
	End "метка точки входа"

Процессоры могут быть 386, 486, 586, обычно всегда стоит 386p, но ничто вам не мешает поставить 486p или 586. Модель памяти всегда flat и никакой другой не может быть. Вызов подпрограмм обычно всегда stdcall, стандарт вызова почти всех API функций. Секция .data секция с инициализированными данными она включается в исполняемый файл. Секция .data? секция с неинициализированными данными, она не включается в исполняемый файл и появляется только тогда, когда программа загружается в память. Секция .const секция констант. Секция .code содержит исполняемый код программы. В конце программы всегда должно стоять слово end, которая задаёт точку входа программы, т.е. место с которого начнётся выполняться программа. Секции .data, .data? имеют полный доступ. Разумеется, секции .const и .code имеют атрибут доступа - только чтение. Секция .const наиболее редко встречается в программах, так как константы можно задавать с помощью макроопределений.

При программировании под Win32 мы не имеем доступ к портам ввода вывода и не можем вызывать прерывания (самые главные команды в DOS), у нас есть только WIN API, которые экспортируют системные библиотеки. Вызывая API функцию, вы просто передаёте управление точке входа функции (точка входа функции это первая инструкция функции), сама функция находится где-то в памяти вашего процесса внутри некоторой библиотеки. API функции находятся в библиотеках kernel32.dll, user32.dll, gdi32.dll (классика) advapi32.dll и т.д., для того чтобы использовать некоторую функцию этих библиотек надо сначала загрузить нужную библиотеку в свою память, либо включить используемые функции в таблицу импорта и тогда загрузчик загрузит библиотеки за вас. О kernel32.dll можно не волноваться, потому что эта библиотека есть в каждом процессе в любом случае, тем более она там существует ещё до запуска главной нити процесса, она даже проецируется в вашу память всегда по одинаковым адресам. Как я уже говорил все функции, используют модель вызова stdcall, а значит, параметры подпрограмме передаются "задом-на-перёд" и вызываемый очищает стек. Общий вид вызова API функции будет такой:

 	Push параметр 3
	Push параметр 2
	Push параметр 1
	Call функция ; если быть точнее то здесь должен стоятб ажрес функции
				; т.е. адрес её точки входа

Каждая программа в Win32 в конце своего выполнения ОБЯЗАТЕЛЬНО должна вызвать функцию ExitProcess. Сами подумайте, после выполнения последней инструкции программы, дальше идёт пустота, даже если там что-то осмысленное, все равно у выделенной памяти есть конец, а после конца идёт невыделенная (т.е. несуществующая) память. Процессор начнёт выполнять непоймёшь чё, пойдут глюки, и ваша программа даст в конце хорошо всем знакомый звук - "ДУНГ". А это уже бессмыслица. Вот определение ExitProcess из MS SDK:

VOID ExitProcess(
    UINT uExitCode 	// exit code for all threads  
   );

uExitCode - это значение никогда не используется и всегда равно 0.

Первая программа.

Теперь я приведу вам программу, которая выводит легендарное сообщение "Hello, World!".

.386                                
.model  flat

extrn ExitProcess:PROC  	
extrn MessageBoxA:PROC

.data    

Ttl	db "First ASSEMBLER program",0h
Msg	db 'Hello, World!!!!',0h

.code

start:
	push 0h
	push offset Msg
	push offset Ttl
	push 0h	
	call MessageBoxA
	push 0h	
	call ExitProcess
end     start

Мы вызываем функцию MessageBoxA, для вывода окна сообщения потом выходим из процесса. Теперь поподробнее.

Определение функции MessageBox из MS SDK в оригинале:

int MessageBox(
    HWND hWnd,	// handle of owner window
    LPCTSTR lpText,	// address of text in message box
    LPCTSTR lpCaption,	// address of title of message box  
    UINT uType 	// style of message box
   );

Мы указали только модель памяти и модель вызов подпрограмм не указали, так как это просто не к чему. В качестве первого параметра мы передаём ноль, поэтому у окна сообщения не будет родительского окна. В качестве параметров lpText и lpCaption мы передаём адреса соответствующих строк, заметьте, что мы передаём адрес строки (т.е. её первого символа) у которой в конце стоит символ #0, это нужно, для того чтобы функция смогла найти конец строки. Последний параметр определяет стиль окна сообщения, в данном случае мы передали 0, что обозначает, что там будет только одна кнопка OK, иначе этот стиль обозначается MB_OK. Функцию ExitProcess вы уже знаете. После директивы end мы указали метку, с которой начнётся выполнение ваша программа.

Зачем нужна буква A в конце функции?

В Win32 есть 2 типа функции заканчивающиеся на A и на W. Всё отличие в строках, которые принимают функции. А-функции принимают ANSI строки. W-функции принимают Unicode строки. У каждой функции, которая принимает строки, есть обе версии. Обычно все пользуются ANSI версиями функций. Но в любом случае при вызове ANSI функции все строки сначала преобразуются в Unicode строки, и будет вызвана Unicode функция.

Компиляция.

Чуть-чуть не забыл рассказать, как надо компилировать программы. Для этого вам надо написать текст программы на ассемблере и сохранить в файл с расширением *.asm. Потом надо ассемблировать его. Для этого вам понадобится программа tasm32.exe она нахидтся в папке %tasmdir%\bin\tasm32.exe, формат её вызова такой: TASM [options] source [,object] [,listing] [,xref] (доп сведения смотрите в tasm32 /?) для большинства программ ассемблирование проходит так:

%tasmdir%\BIN\tasm32 /m3 /ml asmfile,,;

Где asmfile - имя вашего файла БЕЗ расширения.

Потом будет создан объектный файл, файл листинга и т.д. Теперь вам надо всё это слинковать. Для Линковки вам понадобится программа tlink32.exe. Вот формат её вызова:

TLINK objfiles, exefile, mapfile, libfiles, deffile, resfiles

Для всех программ в этом туториале линковка будет такой:

%tasmdir%\BIN\tlink32 /Tpe /aa asmfile,asmfile,,%tasmdir% \Lib\import32.lib 

Где asmfile - имя вашего файла БЕЗ расширения.

Статическая библиотека %tasmdir% \Lib\import32.lib содержит в себе все функции библиотек kernel32.dll, user32.dll, gdi32.dll и может быть других стандартных библиотек. Желательно чтобы asmfile находился в папке %tasmdir%.

Для быстрой компиляции я вам советую создать *.bat файл, который всё это делает за вас. Вот текст моего файла.

Compile.bat
cls
echo off
d:\tasm_5\BIN\tasm32 /m3 /ml %1,,;
d:\tasm_5\BIN\tlink32 /Tpe /aa %1,%1,,d:\TASM_5\Lib\import32.lib
echo "Succesful"

Теперь после вызова

	Compile sample

У вас готовый к выполнению экзешник.

Подошёл к концу четвёртый урок. На этом уроке мы написали первую программу на ассемблере. Но я вам почти не объяснил, как надо пользоваться меткам и данными. Именно, для этого и предназначены 2 следующий урока


Назад | Оглавление | Далее

Оставить комментарий

Комментарий:
можно использовать BB-коды
Максимальная длина комментария - 4000 символов.
 

Комментарии

1.
99K
04 декабря 2017 года
shestak46
0 / / 04.12.2017
Мне нравитсяМне не нравится
4 декабря 2017, 11:41:00
Просьба к автору: по возможности описывать более подробно. Например, каждый шаг выполнения программы, есть ли разница где указывать команду push (например), перед call или можно после? Почему: параметры подпрограмме передаются "задом-на-перёд" при использовании модели вызова stdcall?
В итоге понимается только половина прочитанного.
Повторюсь, это просьба, а не претензия
2.
88K
11 марта 2013 года
dude 01
2 / / 11.03.2013
+1 / -0
Мне нравитсяМне не нравится
11 марта 2013, 16:51:26
люди я установил компилятор TASM на notepad++(awessome)
3.
88K
11 марта 2013 года
dude 01
2 / / 11.03.2013
+1 / -0
Мне нравитсяМне не нравится
11 марта 2013, 16:47:57
да у меня чёт тож не компилится.
Error: Unresolved external 'MESSAGEBOXA' referenced from module main.asm
Error: Unresolved external 'EXITPROCESS' referenced from module main.asm
4.
88K
11 марта 2013 года
dude 01
2 / / 11.03.2013
+2 / -0
Мне нравитсяМне не нравится
11 марта 2013, 15:14:13
было бы офигенно если бы автор выставил ссылку на среду в которой сам работает
5.
90K
11 марта 2013 года
Миша Савельев
1 / / 11.03.2013
+4 / -0
Мне нравитсяМне не нравится
11 марта 2013, 00:50:01
не комилится((( :,(
почему? ((((
создаю бат файл перетаскиваю на него иконку *.asm файла и ничего
6.
70K
27 марта 2011 года
Валенок_шо_ппц
0 / / 27.03.2011
+3 / -2
Мне нравитсяМне не нравится
27 марта 2011, 05:47:04
УРА!! нет на на самом деле... в начале скачал како-то левый ассемблер не хотел устанавливаться - ошибка. Далее пишет что не нашёл IMPORT32.LIB. 3-й долго и упорно требует запистаь программу на дискету или флешку. 4-й установился но отказался собирать не_пойми_почему. И вот стоило скачать 5 раз и всё работает - хотя ничего не понимаю HelloMyWorld !!!
7.
67K
05 января 2011 года
BOTER
0 / / 05.01.2011
+2 / -1
Мне нравитсяМне не нравится
5 января 2011, 11:54:59
"Doctor_Who" Чти что такое стек.
8.
63K
04 августа 2010 года
pitbullko
0 / / 04.08.2010
+2 / -2
Мне нравитсяМне не нравится
4 августа 2010, 22:20:47
Не понятно вот что

.code

start:
push 0h
push offset Ttl
push offset Msg
push 0h
call MessageBoxA
push 0h ---------Зачем нужно в стек запихивать 0? Без этой строчки программа работает также.
call ExitProcess
end start
9.
51K
06 июля 2009 года
триллипут
0 / / 06.07.2009
+1 / -0
Мне нравитсяМне не нравится
9 июля 2009, 12:58:12
а я в бат файле делаю после каждой строчки pause, чтобы посмотреть ошибки
10.
50K
29 мая 2009 года
Doctor_Who
0 / / 29.05.2009
+1 / -0
Мне нравитсяМне не нравится
19 июня 2009, 20:29:50
он мне выводит заголовок хелло ворлд, а сообщение фёрст ассемблер программ, почему?
11.
30K
30 мая 2007 года
demon GRU
0 / / 30.05.2007
+2 / -0
Мне нравитсяМне не нравится
30 мая 2007, 13:28:25
.386
.model flat

extrn ExitProcess:PROC
extrn MessageBoxA:PROC

.data

Ttl db 'First ASSEMBLER program',0h
Msg db "Hello, World!!!!",0h

.code

start:
push 0h
push offset Ttl
push offset Msg
push 0h
call MessageBoxA
push 0h
call ExitProcess
end start
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог