Программирование на языке ассемблера

Федеральное агентство  связи

БФ ГОУ ВПО  СибГУТИ

 

 

 

 

 

 

 

 

 

Курсовая работа

по дисциплине «_______»

 

 

 

 

Выполнил:

Ст-т гр

Пуртов В.

Проверил:

___________

 

 

 

 

 

 

 

 

 

Улан-Удэ, 2005

 

Введение

 

Ассемблером называется машинно-зависимый компилятор, преобразующий специальным образом составленные текстовые строки в машинные инструкции. Как и любой другой компилятор, ассемблер упрощает разработку программ за счет того, что предоставляет пользователю доступ к кодам машинных инструкций и операндам с помощью символьных имен.

Достоинство заключается  в том, что, программируя на ассемблере, программист обычно выбирает последовательность машинных инструкций так, чтобы реализовать  нужные вычисления с максимальной  скоростью при минимальных затратах памяти. С другой стороны,  программирование на уровне машинных инструкций – чрезвычайно хлопотное занятие и не может сравниться по скорости разработки с программированием на языках высокого уровня. В этом заключается главный недостаток ассемблера.

 

 

Постановка задачи:

Написать обработчик прерывания от клавиатуры дописанный спереди с целью введения дополнительного пробела при нажатии на клавишу «Б»

 

Особенности средств разработки и функции прерывания

Управление клавиатурой

 

Клавиатура  содержит Intel-ский микропроцессор, который воспринимает каждое нажатие  на  клавишу  и  выдает скан-код в порт A микросхемы  интерфейса  с  периферией,  расположенной  на системной плате.  Скан-код это однобайтное число, младшие 7 битов которого представляют идентификационный номер, присвоенный каждой клавише. На всех машинах, кроме  AT, старший бит кода говорит о том, была ли клавиша нажата (бит = 1, код нажатия) или  освобождена  (бит = 0, код освобождения).   Когда эта клавиша нажимается, то в порт A посылается  код 10110000, а когда ее отпустили  код 00110000.  Таким образом, каждое нажатие на  клавишу дважды регистрируется в микросхеме 8255.  И каждый раз микросхема 8255 выдает  подтверждение микропроцессору клавиатуры. AT работает немного по-другому, посылая в обоих случаях один и тот же скан-код, но  предваряя  его кодом F0Н, когда клавиша отпускается.

Когда скан-код выдается  в  порт  A,  то вызывается прерывание клавиатуры (INT 9). Процессор моментально  прекращает свою работу и выполняет  процедуру,  анализирующую  скан-код.  Когда поступает код  от  клавиши сдвига или переключателя, то  изменение  статуса записывается в память.  Во всех остальных случаях скан-код трансформируется в код символа, при условии, что он подается при нажатии клавиши (в противном случае, скан-код отбрасывается). Конечно, процедура сначала определяет установку клавиш сдвига и переключателей, чтобы правильно получить  вводимый  код (это "a" или "A"?).  После этого введенный код помещается в буфер клавиатуры, который является областью  памяти, способной запомнить до 15 вводимых  символов, пока программа слишком занята, чтобы обработать их.

Имеется  два  типа  кодов символов, коды  ASCII и  расширенные  коды.  Коды ASCII  это байтные  числа, которые соответствуют расширенному  набору  кодов  ASCII для IBM PC. Для  IBM PC этот набор включает  обычные символы пишущей машинки,  а также ряд специальных букв и символов  псевдографики. ASCII коды включают также 32  управляющих кода,  которые обычно используются  для передачи команд периферийным устройствам, а не выводятся как символы на экране; однако каждый из них имеет соответствующий  символ,  который  может быть выведен на  дисплей,  с использованием прямой адресации дисплейной памяти.

Второй набор  кодов,  расширенные  коды, присвоен клавишам или комбинациям  клавиш, которые не имеют представляющего их  символа ASCII, таким как функциональные клавиши или комбинации с клавишей Alt.   Расширенные коды имеют длину 2 байта, причем  первый  байт всегда ASCII 0.

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

В архитектуре процессоров 80x86 предусмотрены особые ситуации, когда процессор прекращает (прерывает) выполнение текущей программы и  немедленно передает управление программе-обработчику, специально написанной для обработки этой конкретной ситуации. Такие особые ситуации делятся на два типа: прерывания и исключения, в зависимости от того, вызвало ли эту ситуацию какое-нибудь внешнее устройство или выполняемая процессором команда. Исключения делятся далее на три типа: ошибки, ловушки и остановы, в зависимости от того, когда по отношению к вызвавшей их команде они происходят. Ошибки происходят перед выполнением команды, так что обработчик такого исключения получит в качестве адреса возврата адрес ошибочной команды (начиная с процессоров 80286), ловушки происходят сразу после выполнения команды, так что обработчик получает в качестве адреса возврата адрес следующей команды, и наконец, остановы могут происходить в любой момент и вообще не предусматривать средств возврата управления в программу.

Команда INT (а также INTO и INT3) используется в программах как  раз для того, чтобы вызывать обработчики  прерываний (или исключений). Фактически они являются исключениями ловушки, поскольку адрес возврата, который передается обработчику, указывает на следующую команду, но так как эти команды были введены до разделения особых ситуаций на прерывания и исключения, их практически всегда называют командами вызова прерываний. Ввиду того, что обработчики прерываний и исключений в DOS обычно не различают механизм вызова, с помощью команды INT можно передавать управление как на обработчики прерываний, так и исключений.

Как показано в главе 4, программные прерывания, то есть передача управления при помощи команды INT, являются основным средством вызова процедур DOS и BIOS, потому что в отличие от вызова через команду CALL здесь не нужно знать адреса вызываемой процедуры — достаточно только номера. С другой стороны интерфейса рассмотрим, как строится обработчик программного прерывания.

 Обработчики прерываний

Когда в реальном режиме выполняется команда INT, управление передается по адресу, который считывается  из специального массива, таблицы векторов прерываний, начинающегося в памяти по адресу 0000h:0000h. Каждый элемент этого массива представляет собой дальний адрес обработчика прерывания в формате сегмент: смещение или 4 нулевых байта, если обработчик не установлен. Команда INT помещает в стек регистр флагов и дальний адрес возврата, поэтому, чтобы завершить обработчик, надо выполнить команды popf и retf или одну команду iret, которая в реальном режиме полностью им аналогична.

; Пример обработчика  программного прерывания

int_handler     proc     far

                mov      ax,0

                iret

int_handler     endp

После того как обработчик написан, следующий шаг — привязка его к выбранному номеру прерывания. Это можно сделать, прямо записав его адрес в таблицу векторов прерываний, например так:

                push     0         ; сегментный адрес таблицы

                                   ; векторов прерываний

                pop      es        ; в ES

                pushf              ; поместить регистр флагов в  стек

                cli                ; запретить прерывания

; (чтобы не произошло  аппаратного прерывания между  следующими

; командами, обработчик  которого теоретически может  вызвать INT 87h

; в тот момент, когда  смещение уже будет записано, а сегментный

; адрес еще нет, что  приведет к передаче управления

; в неопределенную область памяти)

; поместить дальний адрес  обработчика int_handler в таблицу

; векторов прерываний, в  элемент номер 87h (одно из неиспользуемых  прерываний)

                mov      word ptr es:[87h*4], offset int_handler

                mov      word ptr es:[87h*4+2], seg int_handler

                popf               ; восстановить исходное значение флага IF

Теперь команда INT 87h будет  вызывать наш обработчик, то есть приводить  к записи 0 в регистр АХ.

Перед завершением работы программа  должна восстанавливать все старые обработчики прерываний, даже если это были неиспользуемые прерывания типа 87h. Для этого надо перед предыдущим фрагментом кода сохранить адрес старого обработчика, так что полный набор действий для программы, перехватывающей прерывание 87h, будет выглядеть следующим образом:

                push     0

                pop      es

; скопировать адрес предыдущего  обработчика в переменную old_handler

                mov      eax,dword ptr es:[87h*4]

                mov      dword ptr old_handler,eax

; установить наш обработчик

                pushf

                cli

                mov      word ptr es:[87h*4], offset int_handler

                mov      word ptr es:[87h*4+2], seg int_handler

                popf

; тело программы

[...]

; восстановить предыдущий  обработчик

                push     0

                pop      es

                pushf

                cli

                mov      eax,word ptr old_handler

                mov      word ptr es:[87h*4],eax

                popf

Хотя прямое изменение  таблицы векторов прерываний и кажется  достаточно удобным, все-таки это не лучший подход к установке обработчика  прерывания, и пользоваться им следует  только в случаях крайней необходимости, например внутри обработчиков прерываний. Для обычных программ DOS предоставляет две системные функции: 25h и 35h — установить и считать адрес обработчика прерывания, которые и рекомендуются к использованию в обычных условиях:

; скопировать  адрес предыдущего обработчика  в переменную old_handler

                mov      ax,3587h       ; АН = 35h, AL = номер прерывания

                int      21h            ; функция DOS: считать

                                        ; адрес обработчика прерывания

                mov      word ptr old_handler,bx   ; возвратить

                                                    ; смещение в ВХ

                mov      word ptr old_handler+2,es  ; и сегментный

                                                    ; адрес в ES,

; установить  наш обработчик

                mov      ax,2587h       ; АН = 25h, AL = номер прерывания

                mov      dx,seg int_handler         ; сегментный адрес

                mov      ds,dx                      ; в DS

                mov      dx,offset int_handler      ; смещение в DX

                int      21h                        ; функция DOS: установить

                                                    ; обработчик

; (не забывайте,  что ES изменился после вызова  функции 35h!)

[...]

; восстановить  предыдущий обработчик

                lds      dx,old_handler ; сегментный адрес в DS и смещение в DX

                mov      ax,2587h       ; АН = 25h, AL = номер прерывания

                int      21h            ; установить обработчик

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

При помощи собственных  обработчиков исключений можно справиться и с другими особыми ситуациями, например обрабатывать деление на ноль и остальные исключения, которые могут происходить в программе. В реальном режиме можно столкнуться всего с шестью исключениями:

#DE (деление на ноль) — INT 0 — ошибка, возникающая при переполнении и делении на ноль. Как для любой ошибки, адрес возврата указывает на ошибочную команду.

#DB (прерывание трассировки) — INT 1 — ловушка, возникающая после выполнения каждой команды, если флаг TF установлен в 1. Используется отладчиками, действующими в реальном режиме.

#OF (переполнение) — INT 4 — ловушка, возникающая после выполнения команды INTO, если флаг OF установлен.

#ВС (переполнение при  BOUND) — INT 5 — ошибка, возникающая при выполнении команды BOUND.

#UD (недопустимая команда) — INT 6 — ошибка, возникающая при попытке выполнить команду, отсутствующую на данном процессоре.

#NM (сопроцессор отсутствует) — INT 7 — ошибка, возникающая при попытке выполнить команду FPU, если FPU отсутствует.

Прерывания от внешних  устройств

Прерывания от внешних  устройств, или аппаратные прерывания — это то, что понимается под термином «прерывание». Внешние устройства (клавиатура, дисковод, таймер, звуковая карта и т.д.) подают сигнал, по которому процессор прерывает выполнение программы и передает управление на обработчик прерывания. Всего на персональных компьютерах используется 15 аппаратных прерываний, хотя теоретически возможности архитектуры позволяют довести их число до 64.

Рассмотрим их кратко в порядке  убывания приоритетов (прерывание имеет  более высокий приоритет, и это  означает, что, пока не завершился его  обработчик, прерывания с низкими приоритетами будут ждать своей очереди).

IRQ0 (INT 8) — прерывание системного таймера. Это прерывание вызывается 18,2 раза в секунду. Стандартный обработчик этого прерывания вызывает INT 1Ch при каждом вызове, так что, если программе необходимо только регулярно получать управление, а не перепрограммировать таймер, рекомендуется использовать прерывание 1Ch.

IRQ1 (INT 9) — прерывание клавиатуры. Это прерывание вызывается при каждом нажатии и отпускании клавиши на клавиатуре. Стандартный обработчик этого прерывания выполняет довольно много функций, начиная с перезагрузки по Ctrl-Alt-Del и заканчивая помещением кода клавиши в буфер клавиатуры BIOS.

IRQ2 — к этому входу на первом контроллере прерываний подключены аппаратные прерывания IRQ8 – IRQ15, но многие BIOS перенаправляют IRQ9 на INT 0Ah.

IRQ8 (INT 70h) — прерывание часов реального времени. Это прерывание вызывается часами реального времени при срабатывании будильника и если они установлены на генерацию периодического прерывания (в последнем случае IRQ8 вызывается 1024 раза в секунду).

IRQ9 (INT 0Ah или INT 71h) — прерывание обратного хода луча. Вызывается некоторыми видеоадаптерами при обратном ходе луча. Часто используется дополнительными устройствами (например, звуковыми картами, SCSI-адаптерами и т.д.).

IRQ10 (INT 72h) — используется дополнительными устройствами.

IRQ11 (INT 73h) — используется дополнительными устройствами.

IRQ12 (INT 74h) — мышь на системах PS используется дополнительными устройствами.

IRQ13 (INT 02h или INT 75h) — ошибка математического сопроцессора. По умолчанию это прерывание отключено как на FPU, так и на контроллере прерываний.

IRQ14 (INT 76h) — прерывание первого IDE-контроллера «операция завершена».

IRQ15 (INT 77h) — прерывание второго IDE-контроллера «операция завершена».

IRQ3 (INT 0Bh) — прерывание последовательного порта COM2 вызывается, если порт COM2 получил данные.

IRQ4 (INT 0Ch) — прерывание последовательного порта СОМ1 вызывается, если порт СОМ1 получил данные.

IRQ5 (INT 0Dh) — прерывание LPT2 используется дополнительными устройствами.

IRQ6 (INT 0Eh) — прерывание дисковода «операция завершена».

IRQ7 (INT 0Fh) — прерывание LPT1 используется дополнительными устройствами.

Самые полезные для программ аппаратные прерывания — прерывания системного таймера и клавиатуры. Так как их стандартные обработчики выполняют множество функций, от которых зависит работа системы, их нельзя заменять полностью. Следует обязательно вызвать предыдущий обработчик, передав ему управление следующим образом (Например, если его адрес сохранен в переменной old_handler):

                pushf

                call     old_handler

Эти две команды выполняют  действие, аналогичное команде INT (сохранить флаги в стеке и передать управление подобно команде call), так что, когда обработчик завершится командой IRET, управление вернется в нашу программу. Так удобно вызывать предыдущий обработчик в начале собственного. Другой способ — простая команда jmp:

                jmp      cs:old_handler

приводит к тому, что, когда старый обработчик выполнит команду IRET, управление сразу же перейдет к  прерванной программе. Этот способ применяют, если нужно, чтобы сначала отработал  новый обработчик, а потом он передал бы управление старому.

 

Практическая часть. Разработка алгоритма программы.

Перепрограммирование прерывания клавиатуры

 

   Когда  микропроцессор  клавиатуры помещает скан-код  в  порт  A микросхемы 8255 (адрес  порта  60Н   ), то при этом вызывается прерывание 9.  Задача этого прерывания  преобразовать скан-код символа, основываясь на состоянии клавиш-переключателей, и поместить его в буфер клавиатуры.  (Если скан-код соответствует клавише-переключателю, то в  буфер  клавиатуры не пишется ничего, за  исключением случая клавиши Ins, а вместо  этого  прерывание изменяет  байты  статуса,  расположенные  в  области  данных BIOS).   Прерывания  "ввода с клавиатуры" DOS и BIOS на  самом деле всего лишь прерывания "ввода из буфера клавиатуры". На самом деле они не распознают нажатия клавиш. Точнее, они читают интерпретацию введенных клавиш, которую  обеспечило прерывание 9. 

В прерывании клавиатуры можно выделить три основных шага:

   1.  Прочитать  скан-код и послать клавиатуре подтверждающий сигнал.

   2. Преобразовать скан-код в номер кода или в установку регистра статуса клавиш-переключателей.

   3. Поместить  код клавиши в буфер клавиатуры.

   В  момент вызова  прерывания скан-код будет находиться  в  порте A.  Поэтому сначала надо этот код прочитать и сохранить на стеке. Затем используется порт B (адрес 61Н),  чтобы быстро послать сигнал подтверждения микропроцессору клавиатуры. Надо просто установить бит 7 в 1, а затем сразу  изменить  его  назад в 0. Заметим, что бит 6 порта B управляет сигналом часов клавиатуры.  Он всегда должен быть установлен в 1, иначе клавиатура будет выключена. Эти адреса  портов  применимы и к AT, хотя он и не  имеет  микросхемы интерфейса с периферией 8255.

   Сначала скан-код  анализируется на предмет того, была ли клавиша нажата (код нажатия) или отпущена (код освобождения).  На всех машинах, кроме AT, код освобождения  индицируется установкой бита 7  скан-кода  в 1.  Для AT, у которого бит 7 всегда равен 0,  код освобождения состоит  из  двух  байтов:  сначала  0F0Н,  а  затем скан-код.  Все коды освобождения отбрасываются, кроме случая клавиш-переключателей. С другой стороны, все коды нажатия обрабатываются.

   После  того  как введенный символ  идентифицирован,  процедура ввода с клавиатуры должна найти соответствующий ему код ASCII или расширенный код.  В общем случае  скан-коды  сопоставляются элементам таблицы данных, которая анализируется инструкцией XLAT. XLAT принимает в AL число от 0 до 255, а возвращает в AL  1-байтное значение из 256-байтной  таблицы, на которую указывает DS:BX.

   Наконец, номера  кодов должны быть помещены  в буфер клавиатуры.

Процедура должна сначала проверить, имеется ли в  буфере место для следующего  символа.  Этот буфер  устроен как циклическая очередь. Ячейка  памяти 0040:001A содержит указатель  на  голову буфера, а 0040:001C  указатель на  хвост.   Эти словные указатели дают смещение  в  области  данных BIOS (которая начинается  в сегменте 40Н) и находятся в диапазоне от 30 до  60.

Новые символы вставляются  в ячейки  буфера с более старшими адресами,  а  когда достигнута верхняя граница, то  следующий  символ переносится в нижний конец  буфера.  Когда буфер полон, то указатель хвоста на 2 меньше указателя на голову  кроме случая, когда указатель на голову равен  30  (начало  области буфера), а в этом случае буфер полон, когда указатель хвоста равен 60.

   Для  вставки  символа в буфер, надо поместить  его в позицию, на которую указывает хвост буфера и затем увеличить указатель хвоста на  2; если указатель хвоста был равен 60, то надо  изменить  его значение на 30.  

Перепрограммирование отдельных  клавиш.

    Под  перепрограммированием клавиши понимается способ заставить ее выдавать другой код.  Но к тому времени, когда программа получает  код нажатой клавиши, прерывание клавиатуры уже проинтерпретировало входящий скан-код и преобразовало  его в некоторый заранее  предопределенный код ASCII или расширенный код.  К  счастью, начиная с MS DOS версии 2.0,  система содержит средства перепрограммирования  клавиш.   Это средство действует только  если  ввод воспринимается через  функции  DOS  ввода  с клавиатуры  функции прерывания  BIOS  16Н продолжают интерпретировать нажатия  клавиш нормальным образом.

   Перепрограммирование  доступно за счет Esc последовательностей.  Короткая  строка,  которая начинается с символа Esc  (ASCII  27), предназначается для вывода на  "стандартное  устройство  вывода", т.е.  на терминал.  Но благодаря наличию кода Esc символы даже не достигают монитора.  Вместо  этого такая строка заставляет MS DOS по  другому  интерпретировать клавишу, указанную в  этой  строке. Каждое изменение  клавиши  требует  собственной  строки, при этом один  и тот же код может присваиваться какому  угодно  количеству клавиш.

   Общий  вид такой строки такой: 

27,'[66;98p'   ; данная строка меняет «Б» на «б»

она начинается с кода Esc (ASCII 27),  за которым идет [, затем номер кода переопределяемой клавиши, затем точка с запятой (;), затем новый номер кода, присваиваемый   клавише  и,  наконец,  символ p.  

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

27,'[0;68;0;83p' ; переопределяет F10 (0;68) -> Delete (0;83)

Esc последовательности  ничего  более, чем строки, в которых  первый код или символ указывает какую клавишу нужно  переопределить, а оставшаяся часть строки  указывает какое значение Вы хотите ей придать.   Номера кодов должны быть всегда разделены точкой с запятой, а символы заключены в кавычки. Коды и символы могут быть перемешаны в любых сочетаниях.  Для того  чтобы такие переопределения клавиш были возможны, необходимо чтобы драйвер ANSI.SYS был загружен при загрузке операционной системы. В противном случае Esc последовательности будут игнорироваться.

Имеется  несколько вариантов допустимого вида строки.  Во-первых, символьные клавиши могут обозначаться самим символом, заключенным  в  кавычки. 

Таким образом, строка  27,'["Б";"б"p'  также меняет Б на б.

Во-вторых клавише  может быть присвоена целая строка  символов,  путем указания символов или их кодовых  номеров  в выражении. Строка  27,'["Б";"пробел Б"p' приведет к тому, что при нажатии на клавишу Б в верхнем регистре, будет печататься строчка - пробел Б.

На  самом деле эти  Esc последовательности  ничего более, чем строки, в которых первый код или символ указывает какую клавишу нужно  переопределить, а оставшаяся часть строки  указывает какое значение Вы хотите ей придать.  Коды и символы могут быть перемешаны в любых сочетаниях.  Для того  чтобы такие переопределения клавиш были возможны, необходимо чтобы драйвер ANSI.SYS был загружен при загрузке операционной системы. В  противном случае Esc последовательности будут игнорироваться 

   Реализация программы на языке ассемблер.

Для решения поставленной задачи программный код будет иметь вид приведенный ниже. Используем функцию 9  прерывания  21Н для посылки строки на стандартное  устройство вывода.  DS:DX должны указывать на первый символ строки в памяти  и  строка  должна  завершаться символом $ (24Н).  Здесь клавиша «Б» переопределяется таким образом, чтобы она действовала как строка « Б» (символ пробел и символ заглавная Б).

;в сегменте  данных

CНANGE_КEY   DB   27,'["Б";" Б"p$'

;для изменения  определения клавиши

   LEA  DX,CНANGE_КEY       ;DS:DX должны указывать на строку

   MOV  AН,9                ;номер функции

   INT  21Н                 ;переопределение клавиши

Текст программы:

 

NEW_КEYBOARD  PROC FAR         ;сохраняем все изменяемые

              PUSН AX          ;регистры

              PUSН BX          ;

              PUSН CX          ;

              PUSН DI          ;

              PUSН ES          ;

;получаем скан-код  и посылаем сигнал подтверждения

   IN   AL,60Н         ;получаем  скан-код из порта A

   MOV  AН,AL          ;помещаем копию в AН

   PUSН AX             ;сохраняем скан-код

   IN   AL,61Н         ;читаем  состояние порта B

   OR   AL,10000000B   ;устанавливаем бит  7

   OUT  61Н,AL         ;посылаем измененный байт в  порт

   AND  AL,01111111B   ;сбрасываем бит 7

   OUT  61Н,AL         ;возвращаем состояние порта B

;ES должен указывать  на область данных BIOS

   MOV  AX,40Н         ;устанавливаем сегмент

   MOV  ES,AX          ;

   POP  AX             ;возвращаем скан-код из стека

; установить  наш обработчик

CНANGE_КEY   DB   27,'["Б";" Б"p$'

;для изменения определения клавиши

   LEA  DX,CНANGE_КEY       ;DS:DX должны указывать на строку

   MOV  AН,9                ;номер функции

   INT  21Н                 ;переопределение клавиши

:        POP  ES            ;восстанавливаем изменяемые

             POP DI            ;регистры

             POP  CX            ;

             POP  BX            ;

             POP  AX            ;

             MOV  AL,20Н        ;выдаем сигнал об окончании

             OUT  20Н,AL        ;аппаратного  прерывания

             IRET               ;возврат из прерывания

NEW_КEYBOARD ENDP

 

Вывод

Выполнив данную курсовую работу, я познакомился с программированием на языке ассемблера во всей широте его проявлений — от создания простых программ и процедур, вызываемых из программ на других языках, до драйверов устройств и операционных систем. Теперь должно быть очевидно, что ассемблер не только не сдает свои позиции, но и не может их сдать — ассемблер неотъемлемо связан с компьютером, и всюду, как только мы опускаемся с уровня абстракций языков высокого уровня, рано или поздно встречаемся с ним. В то же время и абстракции, и сложные управляющие структуры, и структуры данных выражаются на языке ассемблера наиболее эффективно. Ассемблер настолько многогранен, что нет никакой возможности описать все. Методы защиты от копирования и противодействия отладчикам, строение различных файловых систем, программирование на уровне портов ввода-вывода.

Программирование на языке ассемблера