Ассемблер.. Вот, как о нем отзывается xakep.ru:
В последнее время ассемблер незаслуженно находится в тени других языков.
Обусловлено это глобальной коммерциализацией, направленной на то, чтобы
в максимально короткие сроки получить как можно большую прибыль от
продукта. Иными словами, массовость взяла верх над элитарностью. А
ассемблер, по моему мнению, ближе к последнему. Гораздо выгоднее в
сравнительно небольшие сроки поднатаскать ученика в таких, например,
языках, как С++, С#, PHP, Java, JavaScript, Python, чтобы он был более-менее
способен создавать ширпотребный софт, не задаваясь вопросами, зачем и
почему он так делает, чем выпустить хорошего специалиста по ассемблеру.
Примером тому служит обширнейший рынок всевозможных курсов по
программированию на любом языке, за исключением ассемблера. Та же
тенденция прослеживается как в преподавании в вузах, так и в учебной
литературе. В обоих случаях вплоть до сегодняшнего дня большая часть
материала базируется на ранних процессорах серии 8086, на так
называемом «реальном» 16-битном режиме работы, операционной среде
MS-DOS! Возможно, что одна из причин в том, что, с одной стороны,
с появлением компьютеров IBM PC преподавателям пришлось перейти
именно на эту платформу из-за недоступности других. А с другой
стороны, по мере развития линейки 80х86 возможность запуска программ
в режиме DOS сохранялась, что позволяло сэкономить деньги на
приобретение новых учебных компьютеров и составление учебников для
изучения архитектуры новых процессоров. Однако сейчас такой выбор
платформы для изучения совершенно неприемлем. MS-DOS как среды
выполнения программ безнадежно устарела уже к середине девяносты
годов, а с переходом к 32-битным процессорам, начиная с процессора
80386, сама система команд стала намного более логичной. Так что
бессмысленно тратить время на изучение и объяснение странностей
архитектуры реального режима, которые заведомо никогда уже не
появятся ни на одном процессоре.Что касается выбора операционной среды для изучения ассемблера, то,
если говорить о 32-битной системе команд, выбор сравнительно невелик.
Это либо операционные системы Windows, либо представители семейства UNIX.Также следует сказать несколько слов о том, какой именно ассемблер
выбрать для той или другой операционной среды. Как известно, для работы
с процессорами х86 используются два типа синтаксиса ассемблера — это
синтаксис AT&T и синтаксис Intel. Эти синтаксисы представляют одни и те же
команды совершенно по-разному. Например, команда
в синтаксисе Intel выглядит так:mov eax,ebx
В синтаксисе же AT&T уже будет иной вид:
movl %eax,%ebx
В среде ОС UNIX более популярен синтаксис типа AT&T, однако учебных
пособий по нему нет, он описывается исключительно в справочной и
технической литературе. Поэтому логично выбрать ассемблер на основе
синтаксиса Intel. Для UNIX-систем есть два основных ассемблера — это
NASM (Netwide Assembler) и FASM (Flat Assembler). Для линейки Windows
популярностью пользуются FASM и MASM (Macro Assembler) от фирмы
Microsoft, и также существовал еще TASM (Turbo Assembler) фирмы Borland,
которая уже довольно давно отказалась от поддержки собственного детища.
Давайте перейдем к самому языку для понимания сущности асма.
Кстати, скачать fasm можно по ссылке: https://flatassembler.net/download.php
напишем "ОС", которая напишет на экран "В":
org 7C00h
mov al, "B"
mov ah, 0Eh
int 10h
cli
hlt
jmp $-2
times 510-$+$$ db 00h
dw 0AA55h
Давайте разберем данный код.
org 07C00h
Подробно поговорим об этом позже, сейчас просто запомните,
что это нужно для такой "ОС" в начале кода.
mov al, "B"
Положим в регистр АL букву В, храниться она, само собой,
будет как число.
mov ah, 0Eh
Положим в регистр АH число 14, это номер команды.
int 10h
возбудим прерывание БИОСа. это прерывание(№10)
работает с экраном и называется "Видеосервис БИОС"
прерывание №10, с командой №14 выводит букву из АL
на экран после последней написанной на экран буквы
и возвращает управление.
cli
Поговорим об этом позже. Просто запомните, что это нужно
для следующей команды.
hlt
Говорим процессору зависнуть.
jmp $-2
Говорим процессору прыгнуть в строку где написано cli,
чтобы снова зависнуть. Требуется, если процессор
каким-то чудом развиснет.
times 510-$+$$ db 00h
Поговорим об этом позже. Запомните, что эта и следующая
строка требуются для такого рода "ОС".
Можете попробовать поиграть с кодом и попробовать
написать "Hello, world!". У вас все получится!
Пришло время серьезно погрузиться
в устройство процессора.
Есть исполнительный блок,
который выполняет ваши команды.
также есть регистры, ячейки
сверхбыстрой памяти.
у процессоров 80х86 есть
4 основных 16-битных регистра:
- ax
- bx
- cx
- dх
Это регистры общего назначения.
каждый из них делится на пары
верхний:нижний регистры в
2 раза меньшей емкости.
основные емкости:
64bit - четверное слово - dq
32bit - двойное слово - dd
16bit - слово - dw
8bit - символ - db
максимальные числа для
каждой емкости:
64bit - 18 446 744 073 709 551 616
32bit - 4 294 967 295
16bit - 65535
8bit - 255
и давайте договоримся называть
емкости "разрядностями", так
корректнее.
И, ах да, нужно же рассказать,
на какие регистры делятся
16битные общего назначения
ax - ah:al
bx - bh:bl
cx - ch:cl
dx - dh:dl
вот и все.
каждый из этих регистров
(ah, al, bh, bl, ...) 8-битной
разрядности, и их порядок
имеет значение.
Итак, мы знаем
как давать команду процессору.
Но что, если её нужно зациклить?
А как же условия? Тут же просто
поочередные команды!
Это главная часть курса. Итак,
начнем с простого.
Напишем библиотеку, которая печатает
на экран и воспользуемся ей.
как это хранится?
Файлы библиотек, или же
подключаемые файлы принято
сохранять с расширением *.inc.
Есть ли отличия? Вообще нет.
Просто это дань времени и
структуризации программы.как создать функцию?
2.1
Функций как таковых в асме нету.
Зато есть метки! и прыжки.
Например, небезопасный метод
зависнуть процессор:
metka: jmp metka
Как можно заметить, метки
обозначаются как "название:".
Ну а если нужно несмотря ни на
что прыгнуть на метку, то
используется конструкция
"JMP название".
Но это не все, поверьте! Есть
и условные прыжки! Для
большинства из них нужно
предварительно вызвать
сравнивающую команду:
"CMP оператор1, оператор2".
В ассемблере есть эти типы прыжков:
JMP, безусловно прыгнуть
JE, оп1 == оп2
JNE, оп1 != оп2
JG, оп1 > оп2
JGE, оп1 >= оп2
JL, оп1 < оп2
JLE, оп1 <= оп2
JZ, активен зеро-флаг
JC, активен кэри-флаг Последние 2 рассмогрим позже.
И так мы можем прыгать на метки.
Удобно ведь?
2.2
А как же функции? Для подобных
нужд в ассемблере есть
директивы "CALL" и "RET".
Пример:
call func
cli
hlt
jmp $-2
func:
do sth
ret
Этот код вызывает функцию func и
зависает. Удобно ведь?
Ближе к делу
давайте разберем работу 10-го
прерывания 14-й команды.
mov ah, 0Eh
int 10h
Итак, оно печатает символ из
AL на экран. Можно применить
метки, чтобы зациклить печать
и поставить условие для выхода
из цикла. А ведь можно обернуть
все в функцию! Вот итоговый код:
file: print.inc
print:
mov ah, 0Eh ; номер команды
loopa:
lodsb ; подгружает в al символ по аддресу из si и увеличивает его на 1
test al, al ; проверяет на разность
jz loopb ; если al == 0, то zero-flag активен(установлен)
int 10h ; возбуждаем прерывание
jmp loopa ; это ведь цикл
loopb:
ret ; выход из функции
file: example.asm
use16
org 7C00h
jmp main
include "print.inc"
msg db "Hello from ColaOS!", 00h
main:
mov si, msg
call print
cli
hlt
jmp $-2
times 510-$+$$ db 00h
dw 0AA55h
Возник вопрос? Подскажу! ;)
П. Ы.: Конструктивная критика приветствуется