Ассемблер. сегменты памяти и регистры

Типы прыжков

Есть 2 типа выполнения условий в ассемблере:

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

   Прыжок с условием (или «условный прыжок») — выполняется с помощью инструкций типа и зависит от самого условия. Условные инструкции, изменяя значение смещения в регистре IP, передают управление, прерывая последовательный поток выполнения кода.

Прежде чем разбираться с этими двумя типами инструкций детально, давайте рассмотрим инструкцию CMP.

7.41 .org NEW-LC, FILL

Продвигает текущий счетчик места до NEW-LC. NEW-LC является или
абсолютным выражением, или выражением с той же секцией, что и текущая
подсекция. Таким образом, Вы не можете использовать директиву .org для
переключения секций; если NEW-LC попадает в другую секцию, то
директива .org игнорируется. Для совместимости с предыдущими
ассемблерами, если секция NEW-LC абсолютная, то as выдает
предупреждение и рассматривает секцию NEW-LC как ту же секцию, что
и данная подсекция.

.org может только увеличить счетчик места, или оставить его таким
же; Вы не можете использовать .org для уменьшения счетчика места.

Поскольку as пытается ассемблировать программу за один проход,
NEW-LC не может быть неопределенным.

Имейте ввиду, что аргумент .org относится к началу секции, а не к
началу подсекции. Это совместимо с другими ассемблерами.

Когда увеличивается счетчик места (текущей подсекции),
вставляемые байты заполняются FILL, который должен быть абсолютным
выражением. Если запятая и FILL опущены, то FILL полагается нулем.

Преимущества и недостатки изучения языка Ассемблера с использованием известных алгоритмических языков Pascal и C/C++

Язык Ассемблера можно изучать по-разному. Можно начинать изучать язык сам по себе, а за результатами следить через отладчик — это обычный, классический путь (см. п. 5.1.1.3).

Можно изучать Ассемблер, делая полноценные ассемблерные модули (но сначала БЕЗ ввода-вывода) и используя в качестве помощников уже известные алгоритмические языки, например, такие, как Pascal или C/C++. В данной книге в основном применен именно этот, ВТОРОЙ, подход. Многолетний и многоассемблерный опыт преподавания убедил автора этой книги в его целесообразности. Используя знакомый алгоритмический язык в качестве помощника и не вникая сначала в особенности ввода-вывода на Ассемблере и организации исполняемых COM- и EXE-файлов, можно начать с простых команд типа a+b (а в Ассемблере, да и в любом алгоритмическом языке ГРАМОТНОЕ решение этой на вид простой задачки дело совсем НЕПРОСТОЕ!). А освоившись с азами программирования на Ассемблере, мы закончим программами на чистом Ассемблере с использованием прерываний и прочих прибамбасов.

Достоинства этого подхода, по мнению автора, заключаются в следующем:

  • Ассемблер осваивается постепенно, от простого к сложному.
  • Готовые модули на Ассемблере пишутся сразу по мере изучения команд.
  • Углубляются знания по уже более-менее освоенному алгоритмическому языку.
  • Используются нормальные и уже знакомые операторы ввода-вывода.
  • Используется родной для освоенной среды программирования отладчик (интегрированный отладчик). Хотя никто НЕ запрещает использовать и более крутые отладчики.
  • Можно подсмотреть (например, в С/С++), как данную задачу решает компилятор и получить чувство глубокого морального удовлетворения, что начинающий программист решает чаще лучше и проще, чем компилятор.

Недостатки:

  • Сразу начинаем работать с разноязычными модулями программ (хотя, возможно, это можно отнести к достоинствам).
  • Нужно хорошо разбираться в вопросах стыковки (интерфейса) разноязычных модулей — этот материал, как в литературе, так и в документации изложен достаточно путано, а чаще всего в книгах по Ассемблеру НЕ излагается вовсе.

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

Есть еще и ТРЕТИЙ путь — использование встроенного Ассемблера. Этот метод мы тоже будем использовать по мере необходимости и там, где это целесообразно. Но встроенный Ассемблер лишен прелести настоящего Ассемблера: он ОЧЕНЬ зависит от среды его реализации и МНОГИХ команд в нем может просто НЕ быть (особенно это касается Borland/Turbo Pascal). Кроме того, зачастую встроенный Ассемблер скрывает (маскирует) КРУПНЫЕ огрехи, которые немедленно возникают в настоящем Ассемблере.

7.54 .stabd, .stabn, .stabs

Эти три директивы, начинающиеся с .stab, формируют символы
(смотрите главу 5 «Символы») для использования их в символических
отладчиках. Эти символы не входят в hash-таблицу as: на них не может
быть как-либо ссылок в исходном файле. Требуется до пяти полей:

STRING

Это имя символа. Оно может содержать любые знаки кроме \000, так
что это более общее понятие, чем обычные имена символов.
Некоторые отладчики используют для кодирования произвольных
сложных структур имена символов, используя это поле.

TYPE

Абсолютное выражение. Тип символа устанавливается в 8 младших бит
этого выражения. Любые битовые маски разрешены, но ld и отладчики
используют самые примитивные битовые маски.

OTHER

Абсолютное выражение. Этот атрибут символа устанавливается в
младшие 8 бит выражения.

DESC

Абсолютное выражение. Дескриптор символа устанавлиается в младшие
16 бит выражения.

VALUE

Абсолютное выражение, которое становится значением символа

Если пpи чтении опеpатоpов .stabd, .stabn или .stabs выдано
пpедyпpеждение, то веpоятно, что эти символы yже были созданы; Вы
получаете наполовину сформированный символ в вашем объектном файле.
Это совместимо с предыдущими ассемблерами!

.stabd TYPE, OTHER, DESC

«Имя» символа не пустая строка. Это null-указатель, для
совместимости. Старые ассемблеры используют null-указатели, так
что они расходуют место в объектном файле на пустые строки.

Значение символа установлено в счетчик места, и способно
изменятся. Когда ваша программа слинкована, значение этого
символа есть адpес счетчика места во вpемя ассемблиpования.stabd.

.stabn TYPE, OTHER, DESC, VALUE

Имя символа yстановлено в пyстyю стpокy.

.stabs STRING, TYPE, OTHER, DESC, VALUE

Все пять полей опpеделены.

Настройка программного окружения

Разработчики данного контроллера предлагают скачать с их сайта некую IDE. Но мы этого делать не будем: только консоль, текстовый редактор и хардкор.

Вот краткий список используемого софта. Что приятно, весь софт присутствует в репозитории, ничего качать с сайта GigaDevice не пришлось.

софт описание
gcc-riscv64-unknown-elf компилятор
stm32flash, dfu-util Прошивальщики через bootloader
kicad Трассировка плат
screen Отладка по UART

Отдельно остановлюсь на прошивке контроллера. Основных способов три:

(1). JTAG — теоретически, самый правильный способ. Вот только подобрать правильное заклинание для него мне так и не удалось
(2). Bootloader.UART — замыкаем вывод Boot0 на питание, ресетим контроллер (можно по питанию, можно вывести кнопку), после чего через stm32flash (да, прошивать можно утилитой, предназначенной для другого семейства!) прошиваем

Ну и наконец притягиваем Boot0 обратно к земле, снова ресетим и смотрим как работает (или как именно не работает) программа
(3). Bootloader.USB — аналогичный предыдущему вариант, только вместо stm32flash используется dfu-util:

Только надо помнить, что для USB важна стабильность тактовой частоты, поэтому если для наших первых опытов хватит встроенного RC-генератора, для USB придется поставить внешний кварц.

Внимательный читатель может заметить, что утилите dfu-util передается некий адрес. Он соответствует началу реальной флеш-памяти контроллера. В нормальном режиме работы этот адрес отображается также и на нулевой адрес, и оттуда же начинается выполнение кода. Если же замкнуть Boot0 на питание, то на тот же нулевой адрес отображается либо Bootloader, либо оперативная память в зависимости от Boot1. В результате работать с контроллером можно вообще не задействуя его флеш, только из оперативки.

Беглый обзор.

Пробежимся по понятиям в ознакомительных целях, более подробно рассмотрим вопрос потом, когда перейдём к 32 битному Windows программированию.

Мы рассчитываем, что вы сами будете изучать выкладываемый код в свободное время. Пользуйтесь созданными для Вас возможностями: DOS-1.rar . TASMED насторен и готов к работе. При внесении изменения в код не забываем жать F2 для сохранения. Если при сборке кода возникает непонятная ошибка (!) — не забываем удалять ранее сгенерированные фалы (с расширениями *.OBJ, *.CODE). Они, как и проекты находятся в папке D:\WORK\Ваша_директория… и будут появляться вновь и вновь при удачной сборке программы. Удалять можно не выходя из DOS: выходим из TASMED (ALT+X), удаляем файлики (в NC — F8) и снова запускаем TASMED — откроется сразу с кодом.

How can multiple sections of file be generated in parallel?

This assembly engine has a single main output that has to be generated
sequentially. This may seem problematic when the file needs to contain
distinct sections for code and data, collected from interleaved pieces that
may be spread across multiple source files. There are, however, a couple of
methods to handle it, all based in one way or another on forward-referencing
capabilities of the assembler.

A natural approach is to define contents of auxiliary section in «virtual»
block and copy it to appropriate position in the output with a single
operation. When a «virtual» block is labeled, it can be re-opened multiple
times to append more data to it.

                include '8086.inc'
                org     100h
                jmp     CodeSection

        DataSection:

                virtual
                        Data::
                end virtual

                postpone
                        virtual Data
                                load Data.OctetString : $ - $$ from $$
                        end virtual
                end postpone

                db Data.OctetString

        CodeSection:

                virtual Data
                        Hello db "Hello!",24h
                end virtual

                mov     ah,9
                mov     dx,Hello
                int     21h

                virtual Data
                        ExitCode db 37h
                end virtual

                mov     ah,4Ch
                mov     al,
                int     21h

This leads to a relatively simple syntax even without help of any additional
macros.

Another method could be to put the pieces of the section into macros and
execute them all at the required position in source. A disadvantage of such
approach is that tracing errors in definitions might become a bit cumbersome.

The techniques that allow to easily append to a section generated in
parallel can also be very useful to generate data structures like relocation
tables. Instead of «store» commands used earlier when demonstrating
the concept, regular data directives could be used inside a re-opened
«virtual» block to create relocation records.

Модели памяти и упрощенные директивы распределения сегментов

Модели памяти задаются директивой .MODEL модель,язык,модификатор  Модель это одно из слов

  • TINY — код данные и стек размещаются в одном и томже сегменте размером до 64Кб.
  • SMALL — код в одном сегменте а данные и стек в другом.
  • COMPACT — код в одном сегменте а под данные выделяется несколько сегментов
  • MEDIUM — код в нескольких сегментах а данные в одном
  • LARGE и HUGE — и код и данные в нескольких сегментах
  • FLAT — то же что и TINY но 32-х разрядный

Язык определяет что процедуры рассчитаны на вызов из подпрограмм на языке высокого уровня. Модификатор определяет будет ли сегмент объединяться с сегментом стэка: NEARSTAK и FARSTACK. После установления модели памяти сегменты можно определить упрощенно! Сегмент кода: .code имя_сегмента Сегмент стэка: .stack размер Сегмент данных: .data Сегмент неинициализированых данных: .data? Сегмент констант: .const Вообще говоря мы так и будем определять модели памяти и сегменты, так компактнее и нагляднее!

Конвенция вызова функций PASCAL (Pascal, Basic, Fortran и др.).

Параметры загоняются в стек слева направо — сверху вниз, стек очищается вызываемой функцией:

Функция (процедура) содержит пять параметров:myFunc (a,b,c,d,e)

;Ассемблерный код:
push a; Первый параметр (самый левый) — сверху
push b; Второй параметр
push c;
push d;
push e; Пятый параметр — снизу
call myFunc

;Функция содержит пять параметров:
myFunc:
push bp
mov bp,sp; Создаём стековый кадр. В bp — указатель на стековый кадр, регистр bp использовать нельзя!
a equ ; Первый параметр — сверху ()
b equ
c equ
d equ
e equ ; Пятый параметр

;команды, которые могут использовать стек:
mov ax,e ; Cчитать параметр 5 — . Можно и так, но это менее понятно: mov ax,
; Его адрес в сегменте стека ВР + 4, потому что при выполнении
; команды CALL при вызове функции, в стек поместили адрес возврата — 2 байта для процедуры
; типа NEAR (или 4 — для FAR), а потом еще и ВР — 2 байта (push bp — в начале нашей функции)
mov bx,с ; считать параметр 3 — . Можно и так, но это менее понятно: mov bx,
; … ещё команды

pop bp
ret 10 ; Из стека дополнительно извлекается 10 байт — стек освобождает вызываемая функция

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

;Ассемблерный код:

pusha; Первый параметр (самый левый) — сверху

pushb; Второй параметр

pushc;

pushd;

pushe; Пятый параметр — снизу

callmyFunc

 
;Функция содержит пять параметров:

myFunc

pushbp

movbp,sp; Создаём стековый кадр. В bp — указатель на стековый кадр, регистр bp использовать нельзя!

aequbp+12; Первый параметр — сверху ()

bequbp+10

cequbp+8

dequbp+6

eequbp+4; Пятый параметр

;команды, которые могут использовать стек:

movax,e; Cчитать параметр 5 — . Можно и так, но это менее понятно: mov ax,

; Его адрес в сегменте стека ВР + 4, потому что при выполнении
; команды CALL при вызове функции, в стек поместили адрес возврата — 2 байта для процедуры
; типа NEAR (или 4 — для FAR), а потом еще и ВР — 2 байта (push bp — в начале нашей функции)

movbx,с; считать параметр 3 — . Можно и так, но это менее понятно: mov bx,

; … ещё команды

popbp

ret10; Из стека дополнительно извлекается 10 байт — стек освобождает вызываемая функция

Директивы данных

Языки высокого уровня (C++, Pascal) являются типизированными. То есть, в них используются данные, имеющие определенный тип, имеются функции их обработки и т. д. В языке программирования ассемблер подобного нет. Существует всего 5 директив для определения данных:

  1. DB — Byte: выделить 1 байт под переменную.
  2. DW — Word: выделить 2 байта.
  3. DD — Double word: выделить 4 байта.
  4. DQ — Quad word: выделить 8 байтов.
  5. DT — Ten bytes: выделить 10 байтов под переменную.

Буква D означает Define.

Любая директива может быть использована для объявления любых данных и массивов. Однако для строк рекомендуется использовать DB.

Синтаксис:

В качестве операнда допустимо использовать числа, символы и знак вопрос — «?», обозначающий переменную без инициализации. Рассмотрим примеры:

Подробнее об адресах

Адрес может передаваться несколькими способами:

  1. В виде имени переменной, которая в ассемблере является синонимом адреса.
  2. Если переменная является массивом, то обращение к элементу массива происходит через имя его переменной и смещения. Для этого существует 2 формы: и <имя>. Следует учитывать, что смещение — это не индекс в массиве, а размер в байтах. Программисту самому необходимо понимать, на сколько нужно сделать смещение в байтах, чтобы получить нужный элемент массива.
  3. Можно использовать регистры. Для обращения к памяти, в которой хранится регистр, нужно использовать квадратные скобки: , .
  4. [] — квадратные скобки допускают применение сложных выражений внутри себя для вычисления адреса: .

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

Помимо этого, в ассемблер существуют сокращения: r — для регистров, m — для памяти и i — для операнда. Эти сокращения используются с числами 8, 16 и 32 для указания размера операнда: r8, m16, i32 и т. д.

Пример на практике

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

section .text
global _start ; должно быть объявлено для линкера (gcc)

_start: ; сообщаем линкеру точку входа
mov edx,len ; длина сообщения
mov ecx,msg ; сообщение для вывода на экран
mov ebx,1 ; файловый дескриптор (stdout)
mov eax,4 ; номер системного вызова (sys_write)
int 0x80 ; вызов ядра

mov edx,9 ; длина сообщения
mov ecx,s2 ; сообщение для написания
mov ebx,1 ; файловый дескриптор (stdout)
mov eax,4 ; номер системного вызова (sys_write)
int 0x80 ; вызов ядра

mov eax,1 ; номер системного вызова (sys_exit)
int 0x80 ; вызов ядра

section .data
msg db ‘Displaying 9 stars’,0xa ; наше сообщение
len equ $ — msg ; длина нашего сообщения
s2 times 9 db ‘*’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

section.text

global_start;должнобытьобъявленодлялинкера(gcc)

_start;сообщаемлинкеруточкувхода

mov edx,len;длинасообщения

mov ecx,msg;сообщениедлявыводанаэкран

mov ebx,1;файловыйдескриптор(stdout)

mov eax,4;номерсистемноговызова(sys_write)

int0x80;вызовядра

mov edx,9;длинасообщения

mov ecx,s2;сообщениедлянаписания

mov ebx,1;файловыйдескриптор(stdout)

mov eax,4;номерсистемноговызова(sys_write)

int0x80;вызовядра

mov eax,1;номерсистемноговызова(sys_exit)

int0x80;вызовядра

section.data

msg db’Displaying 9 stars’,0xa;нашесообщение

len equ$-msg;длинанашегосообщения

s2 times9db’*’

Результат выполнения программы:

Разбор: что значат этот весь текст?

На 1 строчке: «format PE Console» — это строчка говорит FASM-у какой файл скомпилировать, точнее 1 слово, все остальные слова это аргументы (можно так сказать).

PE — EXE файл, программа.

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

Но есть кроме это остальные:

  • format MZ — EXE-файл НО под MS-DOS

  • format PE — EXE-файл под Windows, аналогично format PE GUI 4.0

  • format PE64 — EXE-файл под Windows, 64 битное приложение.

  • format PE GUI 4.0 — EXE-файл под Windows, графическое приложение.

  • format PE Console — EXE-файл под Windows, консольная программа. (просто подключается заранее консоль)

  • format PE Native — драйвер

  • format PE DLL — DLL-файл Windows, поясню позднее.

  • format COFF — OBJ-файл Linux

  • format MS COFF — аналогично предыдущему

  • format ELF — OBJ-файл для gcc (Linux)

  • format ELF64 — OBJ-файл для gcc (Linux), 64-bit

Сразу за командой (для компилятора) идет это значит комментарий. К сожалению он есть только однострочный.

3 строка:

Говорим windows-у где\в каком месте стартовать. «start» это метка, но о метках чуть позже.

5 строка:

Подключает к проекту файл, в данном случае «win32a.inc» он находиться в папке INCLUDE (в папке с FASM). этот файл создает константы и создает макросы для облегчения программирования.

8 строка:

Секция данных, то есть программа делиться на секции (части), к этим секциям мы можем дать разрешение, имя.

Флаг «data» (Флаг это бит\байт\аргумент хранившей в себе какую-то информацию) говорит то что эта секция данных.

Флаги «readable writeable» говорят то что эта секция может читаться кем-то и записываться кем-то.

Текст ‘.data’ — имя секции

10 строка:

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

db — говорит то что под каждый символ резервируем 1 байт. То есть 1 символ храниться в одном байте.

‘hello world!’ — наша строка в кодировке ASCII

Что значит «,0» в конце строки? — это символ с номером 0 (или просто ноль), у вас на клавиатуре нет клавиши которая имела символ с номером 0, по этому этот символ используют как показатель конца строки. То есть это значит конец строки. Просто ноль записываем в байт после строки.

12 строка:

Флаг «code» — говорит то что это секция кода.

Флаг «executable» — говорит то что эта секция исполняема, то есть в этой секции может выполняться код.

Все остальное уже разобрали.

14 строка:

Это второй вид меток. Просто эта метка указывает на следующую команду

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

15 строка:

Функция printf — выводит текст\число в консоль. В данном случае текст по адресу «hello»

Это штото на подобие команды, но это и близко не команда ассемблера, а просто макрос.

Макрос — Это макро команда для компилятора, то есть вместо имени макроса подставляется что-то другое.

Например, макро команда invoke делиться на такие команды: (взят в пример команда с 15 строки)

Не переживайте если нечего не поняли.

17 строка:

getch — функция получения нажатой кнопки, то есть просто ждет нажатия кнопки и потом возвращает нажатую кнопку.

20 строка:

ExitProcess — WinAPI функция, она завершает программу. Она принимает значение, с которым завершиться, то есть код ошибки, ноль это нет ошибок.

23 строка:

Флаг «import» — говорит то что это секция импорта библиотек.

24-25 строки:

Макро команда «library» загружает DLL библиотеки в виртуальную память (не в ОЗУ, вам ОЗУ не хватит чтоб хранить всю виртуальную память).

Что такое DLL объясню позже.

kernel — имя которое привязывается к библиотеке, оно может быть любым.

Следующий текст после запятой: — это имя DLL библиотеки который вы хотите подключить.

Дальше есть знак это значит что текст на следующей строке нужно подставить в эту строку.

То есть код:

Заменяется на:

Это нужно потому что у ассемблера 1 строка это 1 команда.

27-28 строка:

— Макро команда, которая загружает функции из DLL.

— Имя к которой привязана DLL, может быть любым.

— Как будет называться функция в программе, это имя будет только в вашей программе, и по этому имени вы будете вызывать функцию. (WinAPI функция)

— Это имя функции которое будет загружено из DLL, то есть это имя функции которое прописано в DLL.

Дальше думаю не стоит объяснять, вроде все понятно.

Программирование на ассемблер

Написание программы на ассемблере — крайне трудный и затратный процесс

Чтобы создать эффективный алгоритм, необходимо глубокое понимание работы ЭВМ, знание деталей команд, а также повышенное внимание и аккуратность. Эффективность — это критический параметр для программирования на ассемблер

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

Стейтменты

В ассемблере есть три вида стейтментов:

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

   Директивы ассемблера — сообщают программе об аспектах компиляции. Они не генерируют инструкции на машинном языке.

   Макросы — являются простым механизмом вставки кода.

В ассемблере на одну строку приходится один стейтмент, который должен соответствовать следующему формату:

mnemonic

1 меткаmnemonicоперанды;комментарий

Базовая инструкция состоит из названия инструкции () и операндов (они же «параметры»). Вот примеры типичных стейтментов ассемблера:

INC COUNT ; выполняем инкремент переменной памяти COUNT

MOV TOTAL, 48 ; перемещаем значение 48 в переменную памяти TOTAL

ADD AH, BH ; добавляем содержимое регистра BH к регистру AH

AND MASK1, 128 ; выполняем операцию AND с переменной MASK1 и 128

ADD MARKS, 10 ; добавляем 10 к переменной MARKS
MOV AL, 10 ; перемещаем значение 10 в регистр AL

1
2
3
4
5
6
7
8
9
10

INC COUNT;выполняеминкрементпеременнойпамятиCOUNT

MOV TOTAL,48;перемещаемзначение48впеременнуюпамятиTOTAL

ADD AH,BH;добавляемсодержимоерегистраBHкрегиструAH

ANDMASK1,128;выполняемоперациюANDспеременнойMASK1и128

ADD MARKS,10;добавляем10кпеременнойMARKS

MOV AL,10;перемещаемзначение10врегистрAL

Записи с битовыми полями (запись).

Бит — единица данных, может содержать значение 1 или 0. Записи с битовыми полями (records) используют эту возможность.

Каждое битовое поле имеет заданную длину (в битах) и начальное значение. Размер данных типа записи равен сумме длин всех полей

Запись с битовыми полями (запись) — 32 бита.

Опять таки — удобно, экономит место и вычислительное время. Например, чтобы задать цвет точки в изображении (совокупность различных оттенков красного, зелёного, синего (RGB) или свойств окна в операционке Windows.

Не будем подробно разбирать тему, приведём пример кода.

BitMask RECORD f0:4=1,f1:4=1,f2:4=0,f3:4=0

  • xor ax,ax;ax==0
  • mov ax,BitMask;ax==257