Туториал по FASM (Windows x32 API/Win32API), «Hello world!»
Коротко о FASM, ассемблере, WinAPI
Работа с окнами, отрисовка картинок, OpenGL, DirectX, GDI, и все в таком духе.
Взаимодействие с другими процессами.
Работа с консолью Windows
И еще очень много интересных функций.
Зачем нужен ассемблер?
На нем можно сделать все что угодно, от ОС до 3D игр.
Вот плюсы ассемблера:
На нем можно сделать любую программу.
А вот минусы ассемблера:
Долго делать программу. (относительно)
Что нужно для программирования на ассемблере (FASM)?
Это все мероприятие весит всего лишь 8.5MB.
Установка компонентов (если можно так назвать)
Архив FASM-а распаковуем в C:\\FASM\ или любой другой, но потом не забудьте настроить FASMEditor.
Архив FASMEdit-a распаковуем куда-то, в моем случае C:\\FASM Editor 2.0\
Архив OlyDbg распаковуем тоже куда-то, в моем случае C:\\Users\****\Documents\FasmEditorProjects\
Настройка FASM Editor-a
Для этого его нужно запустить.
Сразу вас приветствует FASM Editor соей заставкой.
Жмем на кнопку с названием «. » и выбираем путь к файлам или папкам.
Теперь мы полностью готовы. К началу.
Пишем «Hello world!» на FASM
По началу вас это может напугать, но не боимся и разбираемся.
На самом деле из всей этой каши текста, команд всего 3: на 16, 18, 21 строках. (и то это не команды, а макросы. Мы к командам даже не подобрались)
Все остальное это просто подготовка программы к запуску.
Программа при запуске должна выглядеть так:
Самое интересное то что программа весит 2КБ. (Можно сократить и до 1КБ, но для упрощения и так пойдет)
Разбор: что значат этот весь текст?
Но есть кроме это остальные:
Сразу за командой (для компилятора) format PE Console идет ; это значит комментарий. К сожалению он есть только однострочный.
3 строка: entry start
Говорим windows-у где\в каком месте стартовать. «start» это метка, но о метках чуть позже.
5 строка: include ‘win32a.inc’
Подключает к проекту файл, в данном случае «win32a.inc» он находиться в папке INCLUDE (в папке с FASM). этот файл создает константы и создает макросы для облегчения программирования.
8 строка: section ‘.data’ data readable writeable
Секция данных, то есть программа делиться на секции (части), к этим секциям мы можем дать разрешение, имя.
Флаг «data» (Флаг это бит\байт\аргумент хранившей в себе какую-то информацию) говорит то что эта секция данных.
Флаги «readable writeable» говорят то что эта секция может читаться кем-то и записываться кем-то.
10 строка: hello db ‘hello world!’,0
12 строка: section ‘.code’ code readable writeable executable
Все остальное уже разобрали.
14 строка: start:
Это второй вид меток. Просто эта метка указывает на следующую команду. Обратите внимание на то что в 3 строке мы указали start как метку входа в программу, это она и есть. Может иметь эта метка любое имя, главное не забудьте ваше новое имя метки вписать в entry
15 строка: invoke printf, hello
Это штото на подобие команды, но это и близко не команда ассемблера, а просто макрос.
Например, макро команда invoke делиться на такие команды: (взят в пример команда с 15 строки)
Не переживайте если нечего не поняли.
17 строка: invoke getch
20 строка: invoke ExitProcess, 0
23 строка: section ‘.idata’ data import readable
24-25 строки:
Макро команда «library» загружает DLL библиотеки в виртуальную память (не в ОЗУ, вам ОЗУ не хватит чтоб хранить всю виртуальную память).
Что такое DLL объясню позже.
Дальше есть знак \ это значит что текст на следующей строке нужно подставить в эту строку.
Это нужно потому что у ассемблера 1 строка это 1 команда.
27-28 строка:
Дальше думаю не стоит объяснять, вроде все понятно.
Что такое DLL библиотека?
Это файл с расширением DLL. В этом файле прописаны функции (какие ни будь). Это обычная программа, но которая не запускается по двойному щелчку, а загружается к программе в виртуальную память, и потом вызываются функции находящиеся в этой DLL.
Подводим итог
FasmWorld Программирование на ассемблере FASM для начинающих и не только
Учебный курс. Часть 6. Hello, world!
Автор: xrnd | Рубрика: Учебный курс | 16-03-2010 | Распечатать запись
В этой части наконец-то напишем долгожданный «Hello, world!». Теперь почти всё должно быть понятно. Для начала необходимо с помощью директивы db объявить строку, содержащую сообщение «Hello, word!». Лучше сделать это в конце программы, за последней командой, иначе процессор может принять строку за код и попытаться её выполнить.
Для вывода строки используется системная функция DOS. Чтобы напечатать строку, нужно поместить 9 в регистр AH, а в регистр DX поместить адрес строки, которая должна заканчиваться символом ‘$’. Обращение к функциям DOS осуществляется с помощью команды int 21h. Вот код программы:
use16 ;Генерировать 16-битный код org 100h ;Программа начинается с адреса 100h mov dx,hello ;В DX адрес строки. mov ah,9 ;Номер функции DOS. int 21h ;Обращение к функции DOS. mov ax,4C00h ;\ int 21h ;/ Завершение программы ;——————————————————- hello db ‘Hello, world!$’
В четвёртой строке FASM подставит адрес строки вместо hello. Не трудно догадаться, что завершение программы — это тоже функция DOS с номером 4Ch. Перед её вызовом в регистр AL помещается код завершения программы (ноль соответствует успешному завершению). Можно объединить эти две операции и сразу поместить в AX значение 4C00h.
В учебном курсе я не буду подробно описывать функции DOS, лишь кратко расскажу о тех функциях, которые мы будем использовать. Если вы захотите узнать больше, в Интернете можно найти подробное описание ?
Чтобы увидеть работу программы, надо запустить её из командной строки, иначе она печатает строку и сразу закрывается. Или можно написать простенький bat-файл для запуска:
Результат работы программы:
Если вы запустите программу в отладчике, то просмотреть выводимую строку можно, нажав Alt+F5 или выбрав в меню Turbo Debuger пункт Window->User Screen.
блог alexanius’а
четверг, 12 мая 2016 г.
Пишем «Hello, world» на ассемблере
Так сложилось, что я совсем не знаю ассемблера. Даже несмотря на то, что я разрабатываю компиляторы, на уровень близкий к аппаратуре я почти не спускаюсь. Была пара попыток его выучить, но я просто не находил подходящего материала. В итоге решил что если его нет, то нужно написать самому. В этой заметке я планирую показать как написать простой Hello world на ассемблере.
1. Введение
Я буду стараться давать минимум теории, т.к. её рассказывают много где, гораздо более подробно и понятно. Поэтому буду описывать только то, что касается данного примера.
Итак, задача: написать программу, выводящую на экран сообщение «Hello, world». В качестве эталона возьмём программу на C:
int main()
<
const char * msg = «Hello, world\n»;
write(0, msg, 13);
return 0;
>
Здесь специально не использована стандартная библиотека, а применён системный вызов write. Подробнее про него можно прочесть по команде man 2 write.
2. amd64
Теперь попытаемся понять что произошло.
Краткое описание синтаксиса:
На каждой строчке находятся команды (statement). Команда начинается с нуля и более меток, после которых находится ключевой символ, обозначающий тип команды. Всё что начинается с точки `.’ является директивой ассемблера. Всё что начинается с буквы является инструкцией ассемблера и транслируется в машинный код. Комментарии бывают многострочными `/**/’ и однострочными `#’.
После метки _start начинаются непосредственно ассемблерные инструкции. И теперь опять вернёмся к теории.
Данная программа написана под процессор Intel архитектуры amd64 (она же x86_64). Это 64-х битное расширение архитектуры IA-32. Описание самой архитектуры процессора находится в [intel1]. Подробное описание команд процессора находится в [intel2].
.
#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
.
#define __NR_execve 59
#define __NR_exit 60
#define __NR_wait4 61
.
Понятно, что помимо номеров нам нужны ещё аргументы этих вызовов. Их можно найти следующим образом:
Но в целом таблицами, подготовленными хорошими людьми пользоваться удобнее.
Далее нужно выйти из программы. Для этого используется системный вызов exit. Он имеет номер 60 и требует код возврата в качестве первого аргумента. Мы завершаемся с кодом 0, как и положено успешно выполненной программе.
3. Sparc v9
Не устали? Теперь внезапно рассмотрим sparc. Меня эта платформа интересует, т.к. одна из линеек процессоров Эльбрус основана на этой архитектуре. Я тестировался на процессорах TI UltraSparc III+ (Cheetah+) с ОС Gentoo и процессорах Эльбрус R1000 c ОС Эльбрус. Итак, смотрим:
_start:
! Подготавливаем и вызываем write
mov 1, %o0
set hello_str, %o1
mov hello_str_len, %o2
mov 4, %g1
ta 0x10
Инструкция sethi поместит старшие 22 бита hello_str (т.е. её адрес) на регистр %o2. Инструкция or поместит туда младший остаток. Обозначения %hi и %lo нужны для взятия старших и младших битов соответственно. Такие сложности возникают из-за того что инструкция кодируется 32 битами, и просто не может включать в себя 32-х битную константу.
Далее мы кладём значение 4 на глобальный регистр %g1. Можно догадаться что это номер вызова write. Системный возов будет искать номер вызова именно там.
Далее производятся аналогичные действия для вызова exit, думаю их пояснять не нужно.
Спасибо уважаемому Анониму за версию данной программы для SunOS 5.10:
.msg:
.ascii «Hello world!\n»
.msgend:
4. Эльбрус
Как и Sparc, архитектура Эльбруса рассчитана в первую очередь на то что оптимальный код выдаст компилятор. Но в отличает от Sparc, ассемблер Эльбруса вообще не предназначен для людей. Итак, вот наш пример:
$hello_msg:
.ascii «Hello, world\n\000»
.section «.text»
.global _start
! Вызываем write
<
call %ctpr1, wbs = 0x4
>
! Подготавливаем вызов exit
<
sdisp %ctpr2, 0x1
addd, 0 0x0, 0x0, %b[1]
addd, 1 0x0, 0x1, %b[0]
>
! Вызываем exit
<
call %ctpr2, wbs = 0x4
>
Сборка и запуск:
Мы видим что к синтаксису добавились фигурные скобки. Процессоры Эльбрус основаны на VLIW архитектуре, а значит могут исполнять множество статически спланированных команд за такт. Набор таких команд называется широкой командой (ШК) и заключается в фигурные скобки. Остальной синтаксис более или менее идентичен.
Существует программное соглашение, согласно которому для передачи аргументов в вызываемую процедуру мы используем вращающиеся регистры.
Итак теперь переходим к самой программе. Думаю первые несколько строк и так понятны, поэтому рассмотрим сразу первую ШК:
Далее может возникнуть вопрос зачем в команде addd третья d. В мнемониках команд, реализованных для нескольких форматов операндов, последняя буква обозначает используемый формат. В данном случае мы работаем в double формате, т.е. с полноценным 64-х битным регистром.
В третьей ШК мы аналогичным образом подготавливаем переходы для вызова exit, и в четвёртой ШК мы его вызываем.
Послесловие
Вообще я планировал написать эту заметку за неделю-две и перейти на следующий пример. Более того хотел ещё включить описание llvm IR. Но внезапно простенькая заметка про hello world заняла у меня несколько месяцев. Преимущественно из-за Эльбруса. Тут оказалось много нового и непонятного при почти полном отсутствии читабельной документации. И тут хотелось бы сказать огромное спасибо многим моим коллегам, которые терпеливо в течении долгого времени разъясняли мне простейшие вещи.
MS-DOS и TASM 2.0. Часть 3. Первая программа.
Наша первая программа на ассемблере.
Наша первая программа на ассемблере будет в формате *.COM — как мы уже знаем, исполняемые файлы указанного формата очень крохотные (tiny) по размеру и состоят из одного сегмента, в котором размещаются код, данные и стек.
Ещё мы знаем, что в указанном формате пишутся резидентные программы, драйверы и вирусы.
Резидентная (TSR-программа, от англ. Terminate and Stay Resident) — это программа, которая после запуска передает управление операционной системе, но сама не завершается, а остаётся в оперативной памяти, реагируя на определённые действия пользователя. Например, при нажатии сочетания горячих клавиш делает снимок экрана.
Код в статьях отображается в удобочитаемой форме: каждая строка имеет свой номер, строки и код подсвечиваются. Чтобы скопировать «чистый исходник», наведите курсор мыши на текст, дождитесь всплывающего меню и нажмите в меню кнопочку «копировать» (изображение двух листочков бумаги с текстом). Чистый код не содержит нумерации строк!
Наша первая программа выведет на экран монитора (консоль) надпись «Hello, World!». Итак, как говорил Юрий Алексеевич, поехали!
Создаём исполняемый файл PRG.COM.
Для достижения нашей цели делаем следующее.
Первая строка — запуск транслятора с названием нашего файла с кодом, расположенного в одной директории с транслятором.
Вторая строка — запуск компилятора с параметрами /t /x и название объектного файла — prg.obj, получившегося в результате выполнения первой команды.
Чтобы посмотреть список всех возможных параметров с пояснениями для файлов tasm.exe и tlink.exe необходимо запустить эти программы без параметров. Если вы сделаете это, не выходя из оболочки NC, то, чтобы просмотреть чистое окно DOS нажмите Ctrl+O, чтобы вернуться в NC, нажмите сочетание клавиш повторно.
Батник ASM-EXE.BAT предназначен для создания исполняемого файла формате *.EXE (предусматривает раздельную сегментацию для кода, данных и стека — наиболее распространённый формат исполняемых файлов DOS).
Батник COMPLEX.BAT предназначен для создания исполняемых файлов из двух файлов кода (названия обязательно должны быть prg.asm, prg1.asm).
Наша первая программа на ассемблере прекрасно работает!
TASMED (Tasm Editor) — среда разработки приложений DOS на ассемблере.
Выше мы рассмотрели стандартный подход к программированию на TASM в системе MS-DOS. Указанным алгоритмом создания программ можно пользоваться и далее.
Для более удобной работы с кодом целесообразно применять какую-либо среду разработки. Среда разработки — это громко сказано для времён MS-DOS, правильнее сказать — специфический редактор.
Можете попробывать TASMED в папке D:\UTILS\TASMED\. Программа уже настроена и готова к использованию.
Первая программа на ассемблере в среде разработки TASMED.
Практические советы: группирование проектов, русский язык в MS-DOS.
Для удобства группирования создаваемых программ можно создать отдельную папку (мы создали папку PROJECTS) в которой создавать папки названий проектов, куда копировать соответствующие файлы. Пока у нас — это PRG.ASM, PRG.OBJ, PRG.EXE. Однако, в зависимости от параметров и наших программ их может быть больше (PRG.MAP, PRG.SYM и др.).
В нашем случае, все программы, рассматриваемые в курсе обучения будут группироваться в директории D:\WORK в соответствующих папках. Например, наша первая программа в папке D:\WORK\PRGCOM\ (файлы prg.asm и prg.com). Папку D:\TASM.2_0\PROJECTS\ оставляем пустой для ваших проектов и экспериментов.
Для того, чтобы в исходниках, которые вы будете просматривать в системе MS-DOS с использованием текстовых редакторов DOS и различных сред разработок нормально отображалась кириллица (например в комментариях к строкам кода) необходимо проделать следующие действия.
Конечно вопрос снимается сам собой, если комментарии писать на английском.
В следующей статье мы разберём код нашей первой программы на ассемблере.
Добавить комментарий Отменить ответ
Для отправки комментария вам необходимо авторизоваться.
Изучаем архитектуру Intel x86-64 при помощи ассемблера (Часть 1 — Hello World на голом железе)
Я давно хотел научиться писать операционную систему или хотя бы попробовать эту задачу на зуб. Почему ОС начинают писать на языке ассемблера? Дело в том, что работа ОС обеспечивается определенными особенностями архитектуры процессора. Это, например, наличие нескольких уровней привилегий (режим ядра, режим пользователя), поддержка виртуальной памяти, поддержка многозадачности. Работа с этими особенностями архитектуры процессора подразумевает использование таких машинных команд и регистров процессора, о которых компиляторы высокоуровневых языков программирования (например C/C++) ничего не знают. Поэтому — ассемблер. В следующей серии заметок я буду писать о своих опытах исследования архитектуры процессоров Intel как то: работа в реальном режиме, переход в защищенный режим, написание загрузчика (bootloader), обработка прерываний, включение механизма виртуальной памяти и пр.
В Интернете я нашел несколько хороших ресурсов по теме:
Кроме того, если вы не знакомы с языком ассемблера для процессоров семейства x86, рекомендую вам книгу Kip Irvine — Assembly Language for x86 Processors, 7th edition — 2014.
Начнем с того, что напишем программу HelloWorld, запускающуюся на голом железе (без операционной системы) и запустим ее на виртуальной машине.
Программа HelloWorld
Ниже показан исходный код программы HelloWorld на языке ассемблера Flat Assembler (FASM), которая будет стартовать на голом железе в реальном режиме работы x86-совместимого процессора (комментарии пишу на английском — привычка, которая возникла у меня в связи с проблемами с кодировками кириллицы).
; HelloWorld real mode
use16 ; generate 16-bit code
org 7C00h ; the code starts at 0x7C00 memory address
Компиляция исходного кода
Объяснения того, как работает программа — потом, сначала давайте скомпилируем исходный код. Компилировать будем ассемблером Flat Assembler (FASM). Скачиваем с официального сайта архив с дистрибутивом FASM. Внутри архива находится компилятор fasm.exe. Я рекомендовал бы распаковать архив в папку C:\FASM и добавить путь к этой папке в переменную окружения PATH. Далее запускаем командную строку и компилируем исходный код:
HelloWorld.asm — это приведенный выше файл с исходным кодом, HelloWorld.bin — это скомпилированный машинный код.
Создание образа дискеты
Операционная система должна загружаться с какого-то носителя (жесткого диска, CD-ROM, флешки, дискеты и т. д.). Создадим образ загрузочной дискеты с нашим машинным кодом. Виртуальная машина сможет загрузиться с виртуальной дискеты, используя этот образ. Создавать образ дискеты умеет unix’овая утилита под названием dd. Существует версия этой утилиты под Windows. Если вы пользуетесь средой Cygwin, то утилита dd есть в ее составе. Итак, запускаем командную строку:
1-я команда создает образ дискеты floppy.img и заполняет его нулями, 2-я — записывает в самое начало образа нашу программу.
Установка и запуск виртуальной машины Bochs
Type of floppy drive | 3.5 1.44M |
---|---|
First floppy image/device | жмем Browse и выбираем ранее созданный нами файл floppy.img |
Type of floppy media | 1.44M |
Write Protection | галка снята |
Status | inserted |
Жмем кнопку OK. В окне Bochs Start Menu жмем кнопку Start (предварительно можно сохранить сделанные нами настройки в текстовом файле с расширением .bxrc нажав кнопку Save, впоследствии их можно будет загрузить, нажав кнопку Load). Открывается окно, в котором мы видим надпись
Особенности FASM
Прежде всего обратите внимание на документацию Flat Assembler Documentation and Tutorials, которая также поставляется в дистрибутиве FASM в виде файла PDF. Синтаксис FASM имеет особенности, которые отличают его например от MASM, которым мне доводилось пользоваться до сих пор. Особенности касаются обращений к памяти и работы с метками: