Разное

Ассемблер для чайников – Ассемблер для чайников

Ассемблер Введение

Главная / Ассемблер / Для чайников /

Для начала разберёмся с терминологией.

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

Язык программирования низкого уровня (низкоуровневый язык программирования) – это язык программирования, максимально приближённый к программированию в машинных кодах. В отличие от машинных кодов, в языке низкого уровня каждой команде соответствует не число, а сокращённое название команды (мнемоника). Например, команда ADD – это сокращение от слова ADDITION (сложение). Поэтому использование языка низкого уровня существенно упрощает написание и чтение программ (по сравнению с программированием в машинных кодах). Язык низкого уровня привязан к конкретному процессору. Например, если вы написали программу на языке низкого уровня для процессора PIC, то можете быть уверены, что она не будет работать с процессором AVR.

Язык программирования высокого уровня – это язык программирования, максимально приближённый к человеческому языку (обычно к английскому, но есть языки программирования на национальных языках, например, язык 1С основан на русском языке). Язык высокого уровня практически не привязан ни к конкретному процессору, ни к операционной системе (если не используются специфические директивы).

Язык ассемблера – это низкоуровневый язык программирования, на котором вы пишите свои программы. Для каждого процессора существует свой язык ассемблера.

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

В большинстве случаев говорят «ассемблер», а подразумевают «язык ассемблера». Теперь вы знаете, что это разные вещи и так говорить не совсем правильно. Хотя все программисты вас поймут.

ВАЖНО!
В отличие от языков высокого уровня, таких, как Паскаль, Бейсик и т.п., для КАЖДОГО АССЕМБЛЕРА существует СВОЙ ЯЗЫК АССЕМБЛЕРА. Это правило в корне отличает язык ассемблера от языков высокого уровня. Исходные тексты программы (или просто «исходники»), написанной на языке высокого уровня, вы в большинстве случаев можете откомпилировать разными компиляторами для разных процессоров и разных операционных систем. С ассемблерными исходниками это сделать будет намного сложнее. Конечно, эта разница почти не ощутима для разных ассемблеров, которые предназначены для одинаковых процессоров. Но в том то и дело, что для КАЖДОГО ПРОЦЕССОРА существует СВОЙ АССЕМБЛЕР и СВОЙ ЯЗЫК АССЕМБЛЕРА. В этом смысле программировать на языках высокого уровня гораздо проще. Однако за все удовольствия надо платить. В случае с языками высокого уровня мы можем столкнуться с такими вещами как больший размер исполняемого файла, худшее быстродействие и т.п.

В этой книге мы будем говорить только о программировании для компьютеров с процессорами Intel (или совместимыми). Для того чтобы на практике проверить приведённые в книге примеры, вам потребуются следующие программы (или хотя бы некоторые из них):

  1. Emu8086. Хорошая программа, особенно для новичков. Включает в себя редактор исходного кода и некоторые другие полезные вещи. Работает в Windows, хотя программы пишутся под DOS. К сожалению, программа стоит денег (но оно того стоит))). Подробности см. на сайте http://www.emu8086.com.
  2. TASM – Турбо Ассемблер от фирмы Borland. Можно создавать программы как для DOS так и для Windows. Тоже стоит денег и в данный момент уже не поддерживается (да и фирмы Borland уже не существует). А вообще вещь хорошая.
  3. MASM – Ассемблер от компании Microsoft (расшифровывается как МАКРО ассемблер, а не Microsoft Assembler, как думают многие непосвящённые). Пожалуй, самый популярный ассемблер для процессоров Intel. Поддерживается до сих пор. Условно бесплатная программа. То есть, если вы будете покупать её отдельно, то она будет стоить денег. Но она доступна бесплатно подписчикам MSDN и входит в пакет программ Visual Studio от Microsoft.
  4. WASM – ассемблер от компании Watcom. Как и все другие, обладает преимуществами и недостатками.
  5. Debug — обладает скромными возможностями, но имеет большой плюс — входит в стандартный набор Windows. Поищите ее в папке WINDOWS\COMMAND или WINDOWS\SYSTEM32. Если не найдете, тогда в других папках каталога WINDOWS.
  6. Желательно также иметь какой-нибудь шестнадцатеричный редактор. Не помешает и досовский файловый менеджер, например Волков Коммандер (VC) или Нортон Коммандер (NC). С их помощью можно также посмотреть шестнадцатеричные коды файла, но редактировать нельзя. Бесплатных шестнадцатеричных редакторов в Интернете довольно много. Вот один из них: McAfee FileInsight v2.1. Этот же редактор можно использовать для работы с исходными текстами программ. Однако мне больше нравится делать это с помощью следующего редактора:
  7. Текстовый редактор. Необходим для написания исходных текстов ваших программ. Могу порекомендовать бесплатный редактор PSPad, который поддерживает множество языков программирования, в том числе и язык Ассемблера.
Все представленные в этой книге программы (и примеры программ) проверены на работоспособность. И именно эти программы используются для реализации примеров программ, приведённых в данной книге.

И еще – исходный код, написанный, например для Emu8086, будет немного отличаться от кода, написанного, например, для TASM. Эти отличия будут оговорены.

Большая часть программ, приведённых в книге, написана для MASM. Во-первых, потому что этот ассемблер наиболее популярен и до сих пор поддерживается. Во-вторых, потому что он поставляется с MSDN и с пакетом программ Visual Studio от Microsoft. Ну и в третьих, потому что я являюсь счастливым обладателем лицензионной копии MASM.

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


av-assembler.ru

Ассемблер_для_чайников — Стр 2

Поляков А.В. Ассемблер для чайников.

11

Как мы уже говорили, наша первая программа выводит на экран английскую букву «А». Результат оправдал наши ожидания – буква «А» выведена на экран.

Здесь стоит отметить, что Emu8086 – это ЭМУЛЯТОР, то есть он эмулирует работу компьютера с процессором 8086. Поэтому в описанном выше примере программа выполняется не операционной системой, а эмулятором. Emu8086 может создавать и реальные программы, которые могут самостоятельно выполняться на компьютере. Но описание работы с Emu8086 не входит в наши планы. Читайте справку и экспериментируйте

– всё у вас получится.

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

#make_COM# –1-аястрока. Эта директива – специфическая для Emu8086. Она используется для определения типа создаваемого файла. В нашем случае это файл с расширением .COM.

ORG 100h –2-аястрока. Эта команда устанавливает значение программного счетчика в 100h, потому что при загрузкеСОМ-файлав память, DOS выделяет под блок данных PSP первые 256 байт (десятичное число 256 равно шестнадцатеричному 100). Код программы располагается только после этого блока. Все программы, которые компилируются в файлы типа СОМ, должны начинаться с этой директивы.

MOV AH, 02h –3-ястрока. Инструкция (или команда)MOV помещает значение второго операнда в первый операнд. То есть значение02h помещается в регистрАН. Для чего это делается?02h – это ДОСовская функция, которая выводит символ на экран. Мы пишем программу для DOS, поэтому используем команды этой операционной системы (ОС). А записываем мы эту функцию (а точнее ее номер) именно в регистрАН, потому что прерывание21h использует именно этот регистр.

MOV DL, 41h –4-ястрока. Код символа «A» заносится в регистрDL. Код символа «A» по стандарту ASCII – это41h.

INT 21h –5-ястрока. Это и есть то самое прерывание21h – команда, которая вызывает системную функцию DOS, заданную в регистреАН (в нашем примере это функция02h). КомандаINT 21h – основное средство взаимодействия программ с ОС.

INT 20h –6-ястрока. Это прерывание, которое сообщает операционной системе о выходе из программы и о передаче управления консольному приложению. Значит, при использованииINT 20h в нашем примере, управление будет передаваться программе Emu8086. А в том случае, если программа уже откомпилирована и запущена из ОС, то командаINT 20h вернет нас в ОС (например, в DOS). В принципе, в случае с Emu8086 эту команду можно было бы пропустить, так как эту же функцию выполняет командаRET, которая вставляется в исходный текст автоматически при создании нового файла по шаблону (как это сделали мы ранее). Но я решил использоватьINT 20h и здесь для совместимости с другими ассемблерами.

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

Поляков А.В. Ассемблер для чайников.

12

1.1.2. Debug

Как уже говорилось (см. ВВЕДЕНИЕ), программаDebug входит в состав Windows. Запустить программуDebug можно из командной строки или непосредственно из папки, в которой она находится. Чтобы запустить программу из командной строки, выберите команду из меню ПУСК – ВЫПОЛНИТЬ или нажмите комбинацию клавиш WIN + R (если вы не знаете, что такое комбинация клавиш, см. книгуКомпьютер для чайников). В открывшемся окне (рис. 1.5) напечатайте словоdebug и нажмите клавишу ENTER или щёлкните кнопку ОК.

Рис. 1.5. Запуск программы DEBUG.

После этого откроется окно с пустым экраном и чёрточкой в левом верхнем углу, которая приглашает вас ввести какую-либокоманду. Например, чтобы выйти из программы Debug, напечатайте буквуq и нажмите ENTER.

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

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

Введем букву «а» (напоминаю в последний раз — все команды вводятся на английском языке) и нажмем ENTER.

Затем введем программу, нажимая ENTER в конце каждой строки:

0B72: 0100 MOV AH, 02 0B72: 0102 MOV DL, 41 0B72: 0104 INT 21 0B72: 0106 INT 20 0B72: 0108

Результат будет примерно таким, как показано на рис. 1.6.

ПРИМЕЧАНИЕ 1:

Обратите внимание, что все числовые значения пишутся без буковки h в конце. Это потому, что Debug работает только с шестнадцатеричными числами, и ему не надо объяснять, в какой системе исчисления вводятся данные.

Поляков А.В. Ассемблер для чайников.

13

ПРИМЕЧАНИЕ 2:

После ввода команды -а,появляются символы:0B72: 0100. В вашем случае первые четыре символа могут быть другими, но нас они пока не интересуют. А как вы думаете, что означает число 0100? Помните директиву ORG 100h (см. раздел «1.1.1. Emu8086»)?Вот-вот– это адрес, с которого начинается выполнение программы. То есть в память с этим адресом заносится первая команда программы (для файлов СОМ). Каждая команда занимает 2 байта, поэтому следующий адрес будет 0102 и т.д.

Рис. 1.6. Создание программы в Debug.

Сами команды мы уже знаем (см. раздел «1.1.1. Emu8086»), поэтому описывать их здесь не будем.

Программа написана – нужно проверить ее работу. Нажмём ENTER ещё раз, чтобы на экране появилась чёрточка, которая говорит о том, что можно вводить команду для Debug. Затем введем команду g (от английского «GO») и нажмем клавишу ENTER. На экране увидим следующее:

-gA

Программа завершилась нормально

Здесь A – та самая буква, которая выводится на экран в результате работы программы. Затем идёт сообщение о нормальном завершении программы (оно может отличаться в зависимости от версии Debug).

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

Введем команду t и нажмем клавишу ENTER. Увидим нечто вроде этого:

AX=0200

BX=0000

CX=0000

DX=0000

SP=FFEE

BP=0000

SI=0000

DI=0000

DS=0B72

ES=0B72

SS=0B72

CS=0B72

IP=0102

NV UP EI

PL NZ NA

PO NC

0B72:0102 B241

MOV

DL,41

 

 

 

 

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

Поляков А.В. Ассемблер для чайников.

14

Снова введем команду t и нажмем клавишу ENTER. Увидим следующее:

AX=0200

BX=0000

CX=0000

DX=0041

SP=FFEE

BP=0000

SI=0000

DI=0000

DS=0B72

ES=0B72

SS=0B72

CS=0B72

IP=0104

NV UP EI

PL NZ NA

PO NC

0B72:0104 CD21

INT

21

 

 

 

 

Команда MOV DL, 41, как ей и полагается, записала в регистрDL число41.

Снова введем команду t и нажмем клавишу ENTER. Увидим следующее:

AX=0200

BX=0000

CX=0000

DX=0041

SP=FFE8

BP=0000

SI=0000

DI=0000

DS=0B72

ES=0B72

SS=0B72

CS=0347

IP=0225

NV UP EI

PL NZ NA

PO NC

0347:0225 80FC4B

CMP AH,4B

 

 

 

 

Команды CMP AH,4B нет в нашей программе. Наша программа завершила свою работу. Мы можем долго еще вводить командуt – нам будут выдаваться состояния регистров. Почему это происходит, нам пока не интересно. Лучше введем командуg и нажмем клавишу ENTER, таким образом окончательно выполним нашу программу, и увидим то, что мы уже видели.

Программа написана и проверена. Но как сделать ее самостоятельной, то есть как создать файл СОМ? Ведь то, что мы сделали, работает только с помощью Debug. Чтобы создать исполняемый файл, нужно ответить на несколько вопросов:

1.Какого размера будет наш файл? Выполнение программы начинается с адреса 0100h, а последняя строка в программе содержит адрес 0108h. Это значит, что размер файла будет 8 байт (108h – 100h = 8).

2.Как мы назовем наш файл? А хоть как. Однако, рекомендуется давать файлам английские имена, в которых содержится не более 8 символов (DOSу так приятнее работать). Назовем, например, debug_1.com

Атеперь выполним следующие действия:

1.Снова напишем нашу программу (тренируйтесь, тренируйтесь…).

2.Запишем в регистр СХ размер файла. Для этого введем команду r cx и нажмем ENTER. Затем введем размер файла (8 байт) и нажмем ENTER.

3.Введем команду n, затем один пробел и имя файла. Нажмем ENTER.

4.И, наконец, введем команду w и нажмем ENTER.

В результате всех этих действий на экране появится следующая информация (см. также рис.

1.7):

-rcx СХ 0000 :8

-ndebug_1.com-w

Запись: 00008 байт

Если вы работаете в режиме эмуляции DOS из под WINDOWS, то файл debug_1.com сохранится на рабочий стол, либо в папку текущего пользователя. Это зависит от версии и/или настроек WINDOWS. Теперь его можно запустить как обычную программу. Если в указанных папках вы не нашли этот файл, то найдите его через поиск файлов. Ну а если вы не знаете, как это сделать, см. книгуКомпьютер для чайников.

Чувствую, что мы уже устали. Выход из Debug осуществляется командой q.

Поляков А.В. Ассемблер для чайников.

15

Рис. 1.7. Создание COM-файлас помощью Debug.

Набравшись сил и терпения, изучим еще одну опцию Debug – дизассемблер. С его помощью можно дизассемблироватькакой-нибудьСОМ-файл(то есть выполнить действие, обратное ассемблированию – преобразовать исполняемый файл в исходный код на языке ассемблера). Допустим, у вас есть программка, написанная не вами – ее исходный код вы не знаете, а посмотреть очень хочется. Для этого и существует дизассемблер.

Итак, программа Debug у нас закрыта. Набираем в командной строке:

debug debug_1.com

(где debug_1.com – это имя файла, который мы хотим дизассемблировать) и нажимаем

ENTER.

ПРИМЕЧАНИЕ:

Если программа не запустилась, значит нужно указать полный путь к ней, например

C:\WINDOWS\COMMAND\debug debug_1.com

Если же программа запустилась, но выдала ошибку (например: Ошибка 1282 или «Файл не найден»), то нужно указать полный путь к файлу, например:

C:\WINDOWS\COMMAND\debug C:\MYPROG\debug_1.com

Если и это не помогло, то, возможно, вы всё-такигде-тодопустили ошибку в пути или путь не соответствует требованиям DOS. В таком случае лучше поместить программу в корень диска С, откуда она гарантированно загрузится по пути «C:\debug_1.com».

Поляков А.В. Ассемблер для чайников.

16

Если Debug запустилась без сообщений об ошибках, то вводим команду u и нажимаем ENTER. Вот что мы увидим (примерно, см. также рис 1.8):

-u

 

 

0BC6:0100 B402

MOV

AH, 02

0BC6:0102 B241

MOV

DL, 41

0BC6:0104 CD21

INT

21

0BC6:0106 CD20

INT

20

0BC6:0108 56

PUSH

SI

0BC6:0109 2E

CS:

 

0BC6:010A 8A04

MOV

AL, [SI]

0BC6:010C 0AC0

OR

AL, AL

0BC6:010E 741A

JZ

012A

0BC6:0110 3C3A

CMP

AL, 3A

0BC6:0112 750D

JNZ

0121

0BC6:0114 2E

CS:

 

0BC6:0115 807C0100

CMP

BYTE PTR [SI+01], 00

0BC6:0119 7506

JNZ

0121

0BC6:011B 2E

CS:

 

0BC6:011C C60400

MOV

BYTE PTR [SI], 00

0BC6:011F EB09

JMP

012A

 

 

Рис. 1.8. Дизассемблер Debug.

Посмотрите на первые четыре строки. Узнаете? Это наша программа. Остальные строки нас не интересуют (это инструкции, оставшиеся от программ или данных, отработавших до запуска Debug). Ну а если мы рассматриваем незнакомый файл, как узнать, где кончается программа и начинается «мусор»? Ориентировочно это можно сделать по размеру файла (для очень маленьких программ). Размер можно посмотреть в свойствах файла. Только следует учитывать, что в свойствах файла размер дан в десятичной форме, а Debug нам выдает шестнадцатеричные адреса. Поэтому придется перевести десятичное число в шестнадцатеричное.

Поляков А.В. Ассемблер для чайников.

17

Есть еще вариант (который тоже не всегда приемлем) – найти в полученном списке строку, содержащую команду выхода из программы (INT 20).

Если программа большая, то список ее команд не поместится на экран. Тогда снова вводим команду u и нажимаем ENTER. И так до конца программы.

Возможно, вы не увидите на экране свою программу. Это может быть либо из-затого, что программапочему-тоне загрузилась, либо по причине несоответствия адресов. Будьте внимательны: обращайте внимание на адреса памяти, которые указаны в левой колонке. Наша программа начинается с адреса 0100. Если адрес другой, то это, соответственно, не наша программа.

1.1.3. MASM, TASM и WASM

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

Итак, наша первая программа для MASM, TASM и WASM, которая выводит английскую букву «A» в текущей позиции курсора, то есть в левом верхнем углу экрана:

.model tiny

.code

 

ORG

100h

start: MOV

AH,2

MOV

DL,41h

INT

21h

INT

20h

END

start

Этот текст можно набрать в любом простом текстовом редакторе – например в БЛОКНОТЕ (NotePad) от WINDOWS (но не в Word и не в другом «навороченном»). Однако я рекомендую «продвинутый» текстовый редактор с подсветкой синтаксиса, например, PSPad (см. раздел ВВЕДЕНИЕ). Затем сохраняем этот файл с расширением.asm, например, в папке MYPROG. Назовем файлatest. Итак, мы получили:C:\MYPROG\atest.asm.

ПРИМЕЧАНИЕ:

Обратите внимание, что в первой команде мы записали 2 вместо 02h. MASM, TASM и WASM, как и Emu8086, допускают такие «вольности». Хотя можно написать 02h – ошибки не будет.

Пояснения к программе:

.model tiny –1-аястрока. Директива.model определяет модель памяти для конкретного типа файлов. В нашем случае это файл с расширением COM, поэтому выбираем модельtiny, в которой объединены сегменты кода, данных, и стека. Модельtiny предназначена для создания файлов типа СОМ.

.code –2-аястрока. Эта директива начинает сегмент кода.

ORG 100h –3-аястрока. Эта команда устанавливает значение программного счетчика в 100h, потому что при загрузкеСОМ-файлав память, DOS выделяет под блок данных PSP первые 256 байт (десятичное число 256 равно шестнадцатеричному 100h). Код программы располагается только после этого блока. Все программы, которые компилируются в файлы типа СОМ, должны начинаться с этой директивы.

Поляков А.В. Ассемблер для чайников.

18

start: MOV AH, 02h –4-ястрока. Меткаstart располагается перед первой командой в программе и будет использоваться в директиве END, чтобы указать, с какой команды начинается программа. Инструкция MOV помещает значение второго операнда в первый операнд. То есть значение 02h помещается в регистр АН. Для чего это делается? 02h — это ДОСовская функция, которая выводит символ на экран. Мы пишем программу для DOS, поэтому используем команды этой операционной системы (ОС). А записываем мы эту функцию (а точнее ее номер) именно в регистр АН, потому что прерывание 21h использует именно этот регистр.

MOV DL, 41h –5-ястрока. Код символа «A» заносится в регистр DL. Код символа «A» по стандарту ASCII – это число 41h.

INT 21h –6-ястрока. Это и есть то самое прерывание 21h – команда, которая вызывает системную функцию DOS, заданную в регистре АН (в нашем примере это функция 02h). Команда INT 21h – основное средство взаимодействия программ с ОС.

INT 20h –7-ястрока. Это прерывание, которое сообщает операционной системе о выходе из программы, и о передаче управления консольному приложению. В том случае, если программа уже откомпилирована и запущена из ОС, команда INT 20h вернет нас в ОС (например, в DOS).

END start –8-ястрока. Директива END завершает программу, одновременно указывая, с какой метки должно начинаться ее выполнение.

Ну вот, программу мы написали. Но хотелось бы посмотреть, как она работает. Для этого нужно сначала вызвать ассемблер, чтобы скомпилировать ее в объектный файл, а затем вызвать компоновщик, который из объектного файла создаст исполняемый файл, то есть программу типа COM. Для разных ассемблеров придётся выполнять эти действия по разному.

1.1.3.1. Ассемблирование в TASM

Для TASM создаём объектный файл с именем atest.obj, набрав в командной строке следующую команду:

tasm atest.asm

ПРИМЕЧАНИЕ:

Если на вашем компьютере программа tasm находится не в корневом каталоге диска С:\ и в файлautoexec.bat не внесены соответствующие изменения, то следует указывать полный путь к этой программе. Это касается и файлаatest.asm. В этом случае команда может выглядеть, например, так:

C:\TASM\BIN\tasm C:\MYPROG\atest.asm

Далее следует скомпоновать полученный файл atest.obj в исполняемый файлatest.com. Для этого набираем команду:

tlink /t /x atest.obj

или полный путь:

C:\TASM\BIN\tlink /t /x atest.obj

Обратите внимание, что для файла atest.obj не нужно указывать полный путь, так как он записывается в папку C:\TASM\BIN\. Туда же по умолчанию записывается и готовая к выполнению программаatest.com. Теперь можно ее запустить, и мы увидим то, что должны увидеть – букву «A» в левом верхнем углу экрана.

Поляков А.В. Ассемблер для чайников.

19

ПРИМЕЧАНИЕ:

Если вы работаете в режиме эмуляции DOS из под WINDOWS, то файлы atest.obj иatest.com по умолчанию сохранятся на рабочий стол или в папку пользователя. Это зависит от версии и/или настроек WINDOWS.

1.1.3.2. Ассемблирование в MASM

Для MASM действия аналогичны, только вызов ассемблера и компоновщика несколько отличается. Создание объектного файла:

C:\MASM611\ml /c atest.asm

Компоновка объектного файла:

C:\MASM611\BINR\link /TINY atest.obj,,NUL,,,

Обратите внимание, что ассемблер и компоновщик находятся в разных каталогах. Здесь мы вызываем 16-разрядныйкомпоновщик, который создаёт программы для реального режима DOS. Это справедливо для версии MASM 6.11, для других версий процесс создания может несколько отличаться – см. справку для вашей версии.

Файл atest.com по умолчанию создаётся в том же каталоге, где находятся исходный и объектный файл программы.

1.1.3.3. Ассемблирование в WASM

Для WASM действия аналогичны, только вызов ассемблера и компоновщика несколько отличается. Создание объектного файла:

wasm atest.asm

Компоновка объектного файла:

wlink file atest.obj form DOS COM

1.1.3.4. Выполнение программы

Если у вас всё получилось, то у вас появилась программа atest.com. Теперь её можно запустить на выполнение. Делается это обычным способом для операционной системы. Для ДОС – из командной строки. Для Windows – двойным щелчком по значку программы или также из командной строки.

Однако если вы работаете в Windows, то вы не успеете увидеть результат работы программы, так как окно сразу же закроется после её выполнения. Чтобы этого не произошло, щёлкните правой кнопкой по файлу atest.com и в контекстном меню выберите СВОЙСТВА. В открывшемся окне перейдите на вкладку ПРОГРАММА и снимите галочку «Закрывать окно по завершении работы» (в зависимости от версии Windows эта процедура может немного отличаться).

Поляков А.В. Ассемблер для чайников.

20

Рис. 1.9. Наша первая программа.

После выполнения программы мы увидим на экране то, что и должны были увидеть – английскую букву А (рис. 1.9). Можете немного поэкспериментировать и вместо кода буквы «А» (41h) записать другой код (41h, 42h и т.п. вплоть до 0FFh).

1.1.3.5. Использование BAT-файлов

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

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

Но здесь мы создадим простейший BAT-файл,с помощью которого «лёгким движением руки» мы выполним ассемблирование и компоновку, и создадим исполняемый файл типа COM с помощью ассемблера MASM. Итак, откроем наш любимый текстовый редактор (у меня это PSPad, вы можете воспользоваться блокнотом). Создадим новый файл и напишем там следующий текст:

C:\MASM611\BIN\ml /c atest.asm

PAUSE

C:\MASM611\BINR\link /TINY atest.obj,,NUL,,,

PAUSE

Здесь команда PAUSE приостанавливает выполнение команд BAT-файлаи выводит сообщение «Для продолжения нажмите ENTER…». Само собой, что команды продолжат выполняться после нажатия на ENTER.

Сохраним этот файл с расширением BAT в том же каталоге, где у нас находится исходный файл atest.asm. Назовём его, например,com_create.bat. В результате папка с исходными файлами в проводнике будет выглядеть примерно так, как показано на рис. 1.10.

studfiles.net

Ассемблер_для_чайников — Стр 3

Поляков А.В. Ассемблер для чайников.

21

Рис. 1.10. Файл com_create.bat в ПРОВОДНИКЕ.

Если в вашем случае в графе «Тип» написано не «Пакетный файл MS-DOS»,ачто-тодругое (например, текстовый файл), то это значит, что вы плохо представляете себе, что такое расширение файла. В этом случае настоятельно рекомендую ознакомиться с книгойКомпьютер для чайников.

Теперь выполним этот BAT-файлобычным для Windows способом, то есть дважды щёлкнем по нему левой кнопкой мыши. Что же произойдёт? Операционная система начнёт поочерёдно выполнять команды, записанные в пакетном файле. Сначала выполнится ассемблирование (создание объектного файла). Затем выполнится команда PAUSE. Эта команда здесь для того, чтобы вы могли посмотреть результат ассемблирования. После нажатия клавиши ENTER выполнится компоновка (создание исполняемого файла типа COM, то есть создание готовой программы). Затем снова будет пауза, чтобы вы могли увидеть результат. На экране это будет выглядеть примерно так, как показано на рис. 1.11.

Рис. 1.11. Создание программы на MASM с помощью BAT-файла.

Поляков А.В. Ассемблер для чайников.

22

Конечно, пути в вашем случае будут другими. Как видим, сначала выполняется ассемблирование:

Assembling: attest.asm

Затем выполняется команда PAUSE:

ПутьКВАТФайлу>PAUSE

После нажатия ENTER выполняется компоновка:

LINK: warning L4045: name of output file is ‘atest.com’

Здесь нам сообщают, что компоновщик создал выходной файл attest.com. В чем мы и можем убедиться, заглянув снова в наш каталог с исходными файлами.

Как видите, ассемблирование и компоновка исходных кодов на ассемблере становится не таким уж сложным делом, если подойти к этому творчески. Созданный нами BAT-файлвы можете скопировать в другую папку с другими исходными кодами. Вам останется только заменить имя исходного файла (в тексте выше выделено красным) и файл будет готов к работе с другими исходными кодами.

1.1.4. Шестнадцатеричный редактор

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

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

Написать программу можно и не имея никаких ассемблеров-компиляторови прочих инструментов – с помощьюкакого-либошестнадцатеричного редактора.

ВНИМАНИЕ!

Написание программ с использованием шестнадцатеричного редактора – это не только утомительно, но и НЕБЕЗОПАСНО ДЛЯ КОМПЬЮТЕРА! Так как ошибки в процессе создания программы неизбежны. Но если TASM со товарищи проверяют текст программы на наличие ошибок, то в шестнадцатеричном редакторе проверяющий только один – вы сами. Поэтому, если ошибка останется незамеченной, файл все равно будет создан. И если вы попытаетесь этот «неправильный» файл запустить, то в лучшем случае получите зависание компьютера,

ав худшем этот файл может такое натворить – вирусы отдыхают.

Ивсе-такиразбор программ в шестнадцатеричном редакторе весьма полезен. Особенно тем, кто собирается работать с электроникой – ведь микропроцессоры не понимают ни Паскаль ни С++. Хотя и существуют специальные устройства и программы, которые им эти языки «объясняют».

Для начала вам потребуется шестнадцатеричный редактор. Вы можете использовать любой, имеющийся у вас под рукой. Однако я буду использовать уже упоминавшийся McAfee FileInsight v2.1. Все описанные ниже действия справедливы именно для этого редактора.

Итак, шестнадцатеричный редактор у вас установлен. Запускаем его. Щелкаем по кнопке ОТКРЫТЬ, находим один из созданных нами СОМ-файлов,например,debug_1.com, и загружаем его в редактор.

Поляков А.В. Ассемблер для чайников.

23

Когда файл загружен, в редакторе вы увидите следующее (см. также рис. 1.12):

00000000

B4 02 B2 41 CD 21 CD 20

…A.!.

Можете открыть два других созданных нами файла: mycode.com (созданный в emu8086) илиATEST.COM (который мы создали в разделе «1.1.3. MASM, TASM и WASM»). Увидите то же самое. Это значит, что все ассемблеры создают одинаковый машинный код. То есть отличия в тексте программ не являются принципиальными – они обусловлены только отличиями самих ассемблеров.

Рис. 1.12. Файл DEBUG_1.COM в шестнадцатеричном редакторе.

ПРИМЕЧАНИЕ

Если в вашем случае вы видите другую картину, то либо вы открыли другой файл, либо просматриваете его в текстовом режиме. В последнем случае нажмите кнопку View as Hex на панели инструментов (см. рис. 1.12).

Что же означают эти числа?

С нулями все понятно – это первая ячейка памяти, в которую записано число В4. Это число потом будет записано в адрес 0100h (для СОМ-файла).В строке должно быть 16 чисел, каждое из которых состоит из двух цифр. Числа записываются в шестнадцатеричной форме. Но у нас программа маленькая – всего 8 байт, поэтому и чисел у нас 8.

Поляков А.В. Ассемблер для чайников.

24

Ну а что же такое B4? Это команда – «Ввести значение в регистр АН». А какое значение вводим? Правильно: 02 (следующее в строке число).

Идем дальше. Команда B2 – «ввести значение в регистр DL». Какое значение? Конечно 41. А теперь вспомним, что мы увидели в программе Debug, введя командуt:

AX=0200

BX=0000

CX=0000

DX=0000

SP=FFEE

BP=0000

SI=0000

DI=0000

DS=0B72

ES=0B72

SS=0B72

CS=0B72

IP=0102

NV UP EI

PL NZ NA

PO NC

0B72:0102 B241

MOV

DL,41

 

 

 

 

Видите в последней строке B241? Знакомое сочетание? Это код команды MOV DL, 41.

Идем дальше. CD – код вызова прерывания. Какого? Смотрим следующее число. Итак, CD 21 – это код команды INT 21. Аналогично для CD 20.

Осталось разобраться с загадочными символами в конце строки. А здесь все просто: каждая цифра в числе соответствует коду символа таблицы ASCII, и эти символы выводятся в той же последовательности, что и шестнадцатеричные цифры. В этом тексте вместо некоторых символов стоят точки (.) – это просто коды не буквенных символов.

Ну а теперь напишем и создадим нашу изученную вдоль и поперек программу без ассемблеров и компоновщиков. Открываем редактор, создаём новый файл (для этого щёлкаем кнопку NEW на панели инструментов), затем щёлкаем кнопку View as Hex и вводим данные:

00000000 B4 02 B2 41 CD 21 CD 20

Сохраняем файл под именем, например, hex_1.com. Все. Программа готова. Теперь ее можно запустить и в очередной раз полюбоваться своим творением. Результат будет тот же, что и во всех предыдущих случаях.

И ещё один приятный сюрприз от редактора McAfee FileInsight v2.1 – он имеет свой дизассемблер! Если вы загрузите в редактор исполняемый файл, а в левом нижнем углу выберите вкладку DISASSEMBLY, то сможете посмотреть исходный код загруженной программы на языке ассемблера (рис. 1.12).

Зачем вообще нужны шестнадцатеричные редакторы и дизассемблеры? Ведь это так сложно. Да, это непросто. Однако хакеры так не думают. Именно с помощью шестнадцатеричных редакторов и дизассемблеров они ломают программы. Находят в коде нужные им места и исправляют их в соответствии со своими хакерскими капризами.

Конечно, мы не хакеры. Ломать программы не будем. Однако дизассемблеры и шестнадцатеричные редакторы весьма полезны и законопослушными программистам. Они используются, например, для отладки, для изучения машинных кодов и т.п. Например, вы знаете, как выглядит команда на языке ассемблера, но хотите узнать её машинный код. Если нет документации, то выход только один – шестнадцатеричный редактор и/или дизассемблер. Следует, однако, учесть, что не все команды умещаются в машинный код из двух чисел. Некоторые команды довольно сложные и требуют большего количества чисел для представления в машинных кодах.

Поляков А.В. Ассемблер для чайников.

25

Резюме

В общих чертах мы ознакомились с языком Ассемблера и с разными методами создания программ на этом языке. Подведём некоторые итоги:

1.Язык Ассемблера – это набор мнемонических обозначений команд процессора. Каждый процессор имеет свой набор команд. Мнемоники команд, которые выполняют одинаковые функции, могут отличаться для разных процессоров и/или ассемблеров.

2.Для каждого процессора существует свой ассемблер. Для каждого ассемблера существует свой язык ассемблера, хотя для одинаковых процессоров языки ассемблера могут быть очень похожи.

3.Для каждого процессора существует свой набор регистров. Названия регистров также могут отличаться в зависимости от модели процессора.

4.BAT-файлы– очень полезная вещь. Многие системные администраторы и программисты до сих пор широко используют пакетные файлы, несмотря на то, что сейчас существует множество «скриптовых» языков, таких какVBScript.

5.Ещё одна полезная вещь – шестнадцатеричные редакторы и дизассемблеры. Если вы хотите всерьёз научиться программировать разное «железо», то без них вам не обойтись. Да и в программировании на языках высокого уровня временами возникает необходимость в этих очень полезных инструментах.

Поляков А.В. Ассемблер для чайников.

26

2. ВВЕДЕНИЕ В АССЕМБЛЕР

Если вы в полной мере удовлетворили своё любопытство, прочитав раздел Быстрый старт, значит душа ваше не предрасположена к программированию на языке Ассемблера. В этом случае, быть может, вам стоит попробовать программирование на языках высокого уровня или вообще сменить профессию/хобби.

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

Но хватит лирики. Пора начать разговор по теме. В этом разделе мы рассмотрим не только основы программирования на языке ассемблера, но и такие необходимые вещи, как системы счисления, устройство процессора и компьютера в целом, организацию памяти и многое другое. Всё это крайне необходимо знать и понимать, потому что программируя на языке ассемблера, вы будете напрямую работать с регистрами процессора, с памятью и железом. Для вычисления математических выражений вам нужно чётко понимать, как различные числа представлены в памяти компьютера. Также вам нужно знать, как вообще работает процессор (и компьютер), иначе вы не сможете чувствовать себя уверенно при написании программ на языке ассемблера.

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

В данной книге мы будем говорить только о программировании для 16-разряднойОС DOS. Однако это не должно вас смущать.Во-первых,существуют эмуляторы, где вы можете в полной мере протестировать ваши программы.Во-вторых,программы, написанные для DOS, в большинстве случаев будут нормально работать под Windows.В-третьих,в большинстве случаев программы для Windows лучше создавать с помощь современных визуальных средств разработки, таких как Delphi или Visual Basic. Ну и,в-четвёртых,в будущих изданиях этой книги я обязательно добавлю разделы по программированию для Windows.

2.1. Как устроен компьютер

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

1.Процессор

2.Оперативная память (ОЗУ)

3.Устройства ввода-вывода

4.Шина данных

5.Шина адреса

6.Шина управления

Впринципе этого достаточно для решения большинства задач.

Поляков А.В. Ассемблер для чайников.

27

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

Устройства ввода-вывода предназначены для взаимодействия с пользователем и другими устройствами. Например, монитор предназначен для вывода информации пользователю. Клавиатура предназначена для получения информации от пользователя, то есть для ввода информации.

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

Шина (bus) – это группа параллельных проводников, с помощью которых данные передаются от одного устройства к другому. Обычно компьютер состоит из трёх шин:

Шина данных (data bus) используется для обмена команд и данных между процессором и оперативной памятью, а также между устройствамиввода-выводаи ОЗУ.

Шина управления (control bus) используется для передачи специальных сигналов, которые синхронизируют работу всех устройств, подключенных к системной шине. Например, процессор должен знать, когда можно читать информацию с шины данных. Для этого используется специальный сигнал готовности шины данных.

Шина адреса (address bus) используется для указания адреса ячейки памяти в ОЗУ, к которой в текущий момент происходит обращение со стороны процессора или устройстваввода-вывода(чтение или запись).

Самый основной элемент компьютера, это, конечно, процессор. Об устройстве процессора мы будем говорить в следующем разделе.

2.1.1. Структура процессора

Упрощённая структура процессора показана на рис. 2.1.

Рис. 2.1. Структура процессора.

Поляков А.В. Ассемблер для чайников.

28

Основные элементы процессора:

Регистры АЛУ – арифметико-логическоеустройство

БУ – блок управления ТГ – тактовый генератор

Регистры – это специальные ячейки памяти, физически расположенные внутри процессора. В отличие от ОЗУ, где для обращения к данным требуется использовать шину адреса, крегистрам процессор может обращаться напрямую. Это существенно ускорят работу с данными.

Арифметико-логическое устройство выполняет арифметические операции, такие как сложение, вычитание, а также логические операции.

Блок управления определяет последовательность микрокоманд, выполняемых при обработке машинных кодов (команд).

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

В теории электронно-вычислительныхмашин различают два понятия: машинный такт и машинный цикл.

Машинный такт соответствует одному периоду импульсов тактового генератора и является основной единицей измерения времени выполнения команд процессором.

Машинный цикл состоит из нескольких машинных тактов. Машинный цикл – это время, необходимое для выполнения одной команды.

Машинный цикл может отличаться для разных команд. Для простых команд может потребоваться всего 1-2машинных такта. В то время как для сложных команд, таких как умножение, может потребоваться до 50 машинных тактов и более. Это очень важный момент. Когда вы будете писать реальные программы, которые очень критичны к быстродействию, следует помнить о том, что разные команды требуют соответствующего времени работы процессора. То есть одни и те же действия можно выполнить, например, за 100 машинных тактов, а можно и за 20. Это зависит от опыта и квалификации программиста, а также от конкретных задач.

Доработка программы таким образом, чтобы она выполнялась максимально быстро (то есть для её выполнения требовалось как можно меньше машинных тактов) называется оптимизация по быстродействию. В таких случаях часто приходитсячем-тожертвовать, например, усложнять программу или увеличивать её размер. Есть и другие типы оптимизации, например,оптимизация по размеру. В этом случае обычно жертвуют быстродействием, чтобы получить программу с минимальным размером исполняемого файла. Выбор оптимизации зависит от конкретной задачи. Вопросы оптимизации будут рассмотрены в соответствующем разделе.

Поляков А.В. Ассемблер для чайников.

29

2.1.2. Регистры процессора

Начиная с модели 80386 процессоры Intel предоставляют 16 основных регистров для пользовательских программ и ещё 11 регистров для работы с мультимедийными приложениями (MMX) и числами с плавающей точкой (FPU/NPX). Все команды так или иначе изменяют содержимое регистров. Как уже говорилось, обращаться к регистрам быстрее и удобнее, чем к памяти. Поэтому при программировании на языке Ассемблера регистры используются очень широко.

В этом разделе мы рассмотрим основные регистры процессоров Intel. Названия и состав/количество регистров для других процессоров могут отличаться. Итак, основные регистры процессоров Intel.

Таблица 2.1. Основные регистры процессора.

Название

Разрядность

Основное назначение

EAX

32

Аккумулятор

EBX

32

База

ECX

32

Счётчик

EDX

32

Регистр данных

EBP

32

Указатель базы

ESP

32

Указатель стека

ESI

32

Индекс источника

EDI

32

Индекс приёмника

EFLAGS

32

Регистр флагов

EIP

32

Указатель инструкции (команды)

CS

16

Сегментные регистры

DS

16

 

ES

16

 

FS

16

 

GS

16

 

SS

16

 

Регистры EAX, EBX, ECX, EDX – это регистры общего назначения. Они имеют определённое назначение (так уж сложилось исторически), однако в них можно хранить любую информацию.

Регистры EBP, ESP, ESI, EDI – это также регистры общего назначения. Они имеют уже более конкретное назначение. В них также можно хранить пользовательские данные, но делать это нужно уже более осторожно, чтобы не получить «неожиданный» результат.

Регистр флагов и сегментные регистры требуют отдельного описания и будут более подробно рассмотрены далее.

Пока для вас здесь слишком много непонятных слов, но со временем всё прояснится)))

Когда-топроцессоры были16-разрядными,и, соответственно, все их регистры были также16-разрядными.Для совместимости со старыми программами, а также для удобства программирования некоторые регистры разделены на 2 или 4 «маленьких» регистра, у каждого из которых есть свои имена. В таблице 2.2 перечислены такие регистры.

Поляков А.В. Ассемблер для чайников.

30

Вот пример такого регистра.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Разряд (бит)

 

 

Регистр (32 бита)

 

 

Регистр (16 бит)

 

 

Регистр (8 бит)

 

 

31

 

 

 

 

 

 

 

 

 

 

 

30

 

 

 

 

 

 

 

 

 

 

 

29

 

 

 

 

 

 

 

 

 

 

 

28

 

 

 

 

 

 

 

 

 

 

 

27

 

 

 

 

 

 

 

 

 

 

 

26

 

 

 

 

 

 

 

 

 

 

 

25

 

 

 

 

 

 

 

 

 

 

 

24

 

 

 

 

 

Старшие разряды регистра EAX

 

23

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

22

 

 

 

 

 

 

 

 

 

 

 

21

 

 

 

 

 

 

 

 

 

 

 

20

 

 

 

 

 

 

 

 

 

 

 

19

 

 

 

 

 

 

 

 

 

 

 

18

 

 

 

 

 

 

 

 

 

 

 

17

 

 

 

 

 

 

 

 

 

 

 

16

 

 

EAX

 

 

 

 

 

 

 

 

 

15

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

14

 

 

 

 

 

 

 

 

 

 

 

 

13

 

 

 

 

 

 

 

 

 

 

 

 

12

 

 

 

 

 

 

 

 

AH

 

 

 

 

 

 

 

 

 

 

 

 

 

11

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

10

 

 

 

 

 

 

 

 

 

 

 

 

9

 

 

 

 

 

 

 

 

 

 

 

 

8

 

 

 

 

 

AX

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

7

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6

 

 

 

 

 

 

 

 

 

 

 

 

5

 

 

 

 

 

 

 

 

 

 

 

 

4

 

 

 

 

 

 

 

 

AL

 

 

 

 

 

 

 

 

 

 

 

 

 

3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2

 

 

 

 

 

 

 

 

 

 

 

 

1

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

 

 

Из этого следует, что вы можете написать в своей программе, например, такие команды:

MOV AX, 1

MOV EAX, 1

Обе команды поместят в регистр AX число 1. Разница будет заключаться только в том, что вторая команда обнулит старшие разряды регистра EAX, то есть после выполнения второй команды в регистре EAX будет число 1. А первая команда оставит в старших разрядах регистра EAX старые данные. И если там были данные, отличные от нуля, то после выполнения первой команды в регистре EAX будет какое-точисло, но не 1. А вот в регистре AX будет число 1. Сложно? Ну это пока… Со временем вы к таким вещам привыкните.

Мы пока не говорили о разрядах (битах). Эту тему мы обсудим в разделах, посвящённых системам счисления. А сейчас пока вам достаточно знать, что нулевой разряд (бит) – это младший бит. Он крайний справа. Старший бит – крайний слева. Номер старшего бита зависит от разрядности числа/регистра. Например, в 32-разрядномрегистре старшим битом является31-йбит (потому что отсчёт начинается с 0, а не с 1).

Ниже приведён список регистров общего назначения, которые можно поделить описанным выше способом и при этом к «половинкам» и «четвертинкам» этих регистров можно обращаться в программе как к отдельному регистру.

studfiles.net

Ассемблер_для_чайников — Стр 4

Поляков А.В. Ассемблер для чайников.

 

31

Таблица 2.2. «Делимые» регистры.

 

 

 

 

 

 

 

 

 

Регистр

Старшие разряды

Имена 16-тии8-мибитных регистров

 

 

31…16

15…8

 

7…0

 

EAX

 

 

AX

 

 

 

AH

 

AL

 

EBX

 

 

BX

 

 

 

BH

 

BL

 

ECX

 

 

CX

 

 

 

CH

 

CL

 

EDX

 

 

DX

 

 

 

DH

 

DL

 

ESI

 

 

SI

 

EDI

 

 

DI

 

EBP

 

 

BP

 

ESP

 

 

SP

 

EIP

 

 

IP

 

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

2.1.3. Цикл выполнения команды

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

Для того чтобы процессор знал, какую команду нужно выполнять в определённый момент, существует счётчик команд – специальныйрегистр, в котором хранится адрес команды, которая должна быть выполнена после выполнения текущей команды. То есть при запуске программы в этом регистре хранится адрес первой команды. В процессорах Intel в качестве счётчика команд (его ещё называютуказатель команды) используется регистр EIP (или IP в16-разрядныхпрограммах).

Счётчик команд работает со сверхоперативной памятью, которая находится внутри процессора. Эта память носит название очередь команд, куда помещается одна или несколько команд непосредственно перед их выполнением. То есть в счётчике команд хранится адрес команды в очереди команд, а не адрес оперативной памяти.

Цикл выполнения команды – это последовательность действий, которая совершается процессором при выполнении одной машинной команды. При выполнении каждой машинной команды процессор должен выполнить как минимум три действия: выборку, декодирование и выполнение. Если в команде используется операнд, расположенный в оперативной памяти, то процессору придётся выполнить ещё две операции: выборку операнда из памяти и запись результата в память. Ниже описаны эти пять операций.

Поляков А.В. Ассемблер для чайников.

32

Выборка команды. Блок управления извлекает команду из памяти (из очереди команд), копирует её во внутреннюю память процессора и увеличивает значение счётчика команд на длину этой команды (разные команды могут иметь разный размер).

Декодирование команды. Блок управления определяет тип выполняемой команды, пересылает указанные в ней операнды в АЛУ и генерирует электрические сигналы управления АЛУ, которые соответствуют типу выполняемой операции.

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

Выполнение команды. АЛУ выполняет указанную в команде операцию, сохраняет полученный результат в заданном месте и обновляет состояние флагов, по значению которых программа может судить о результате выполнения команды.

Запись результата в память. Если результат выполнения команды должен быть сохранён в памяти, блок управления начинает операцию сохранения данных в памяти.

Суммируем полученные знания и составим цикл выполнения команды:

1.Выбрать из очереди команд команду, на которую указывает счётчик команд.

2.Определить адрес следующей команды в очереди команд и записать адрес следующей команды в счётчик команд.

3.Декодировать команду.

4.Если в команде есть операнды, находящиеся в памяти, то выбрать операнды.

5.Выполнить команду и установить флаги.

6.Записать результат в память (по необходимости).

7.Начать выполнение следующей команды с п.1.

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

2.1.4. Организация памяти

С точки зрения процессора память – это последовательность байтов, каждому из которых присвоен уникальный адрес со значениями от 0 до (232 – 1), то есть до 4 ГБ. Конечно, сейчас есть64-разрядныепроцессоры. Но о них в этой книге мы говорить не будем.

Программы могут работать с памятью как с одним непрерывным массивом (модель памяти flat – плоская) или как с несколькими массивами (сегментированные модели памяти). Во втором случае для задания адреса любого байта требуется два числа – адрес начала массива и адрес байта внутри этого массива.

Кроме основной памяти программы могут использовать регистры процессора, о которых говорилось выше.

Выбор метода обращения к памяти определяется режимом работы процессора. Процессоры Intel могут работать в одном из трёх основных режимах:

Реальный режим (режим реальной адресации –Real-addressmode)Защищённый режим (Protected mode)

Режим управления системой (System Management mode)

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

Поляков А.В. Ассемблер для чайников.

33

Вреальном режиме процессор может обращаться только к первому мегабайту памяти, адреса которого находятся в диапазоне 00000…FFFFF. При этом процессор работает в однопрограммном режиме, то есть одновременно может выполняться только одна программа. Реальный режим работы используется в операционной системе DOS, а также в системах Windows 95/98 при загрузке в режиме эмуляции DOS.

Взащищённом режиме процессор может одновременно выполнять несколько программ. При этом каждой программе может быть назначено до 4 ГБ оперативной памяти. Чтобы предотвратить влияние программ друг на друга, им выделяются изолированные участки памяти. Поэтому режим и называется защищённым. В защищённом режиме работают такие системы как Windows и Linux.

Об организации памяти в реальном и защищённом режимах мы поговорим в следующих разделах. А пока рассуждения о памяти закончим. Тема эта большая и для кого-томожет оказаться сложной. К ней мы ещё будем возвращаться. Некоторую информацию о сегментированных моделях памяти можно найти здесь:Контрольная работа по информатике.

2.1.5. Реальный режим

Вреальном режиме процессор может обращаться только к первым 1 048 576 байтам (1 МБ) оперативной памяти, так как в реальном режиме используется только 20 младших разрядов шины адреса. Из этого следует, что диапазон адресов памяти (в шестнадцатеричном представлении) будет от 00000 до FFFFF. А повелось это с тех времён, когда шина адреса была 20-разрядной,а регистры16-разрядными.То есть одного регистра было недостаточно для хранения адреса.

Вреальном режиме используется сегментная модель памяти. Суть её заключается в том, что всё доступное адресное пространство разделено на блоки по 64 КБ. Такие блоки называются

сегментами.

Пример записи адреса в сегментной модели памяти:

8000:0100

Здесь 8000 – это адрес сегмента (или просто сегмент), а 0100 – это смещение относительно адреса сегмента (или простосмещение). Таким образом, чтобы получить доступ к какомулибо байту в памяти в реальном режиме, нужно знать сегмент и смещение, то есть начало64-килобайтногоблока памяти, где находится нужный нам байт, и смещение от начала этого блока, то есть адрес (номер) байта в этом блоке. Напомню, что нумерация начинается с нуля, а не с единицы.

Реальный адрес (линейный адрес) нужного нам байта определяется следующим образом (упрощено в расчёте на начинающих, профессионалов прошу отнестись с пониманием). Берём сегмент и приписываем к нему нолик справа, то есть в нашем примере получим 80000. Затем прибавляем к полученному числу смещение. Получаем 80100 – это и есть линейный адрес, то есть адрес, который используется в 20-разряднойшине адреса для доступа к байту. Операцию преобразования сегментного адреса в линейный адрес выполняетсумматор адреса – специальное аппаратное устройство, которое входит в состав процессора.

Напомню, что все адреса в данном разделе представлены в шестнадцатеричной системе.

Ещё немного наглядной информации о сегментных и линейных адресах вы можете найти здесь: Контрольная работа по информатике.

Поляков А.В. Ассемблер для чайников.

34

2.1.6. Защищённый режим

При работе в защищённом режиме каждой программе может быть выделен блок памяти размером до 4 ГБ. Адреса этого блока в шестнадцатеричном представлении могут меняться от 00000000 до FFFFFFFF. В защищённом режиме программе выделяется линейное адресное пространство (flat address space), которое разработчики компилятора Microsoft Assembler назвалилинейная модель памяти (flat memory model) илиплоская модель памяти.

С точки зрения программиста линейная модель памяти более проста в использовании, так как для хранения адреса любой переменной или команды достаточно одного 32-разрядногорегистра.

Ну что же. На первый раз информации об организации памяти достаточно. Подозреваю, что даже эту информацию многие читатели просмотрели «по диагонали». Это объяснимо – тема довольно сложная, если вы сталкиваетесь с этим в первый раз. Рекомендую приступить к изучению следующих разделов, а к памяти мы ещё вернёмся…

2.2. Системы счисления

Системы счисления (они же системы исчисления) – это способы представления чисел. Самой распространённой среди людей системой счисления являетсядесятичная система счисления. В этой системе каждое число может быть представлено комбинацией из десяти цифр от 0…9. Однако это не единственная система счисления в истории. Например, у эскимосов была двадцатеричная система счисления.

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

В мире компьютерном наиболее часто используются следующие системы счисления:

Двоичная система счисления Восьмеричная система счисления Шестнадцатеричная система счисления

Основой основ является двоичная система счисления. Почему? Так сложилось исторически. Подробнее см. в книгеКак стать программистом в разделе «Как устроен компьютер». А теперь рассмотрим двоичную систему более подробно.

2.2.1. Двоичная система счисления

Чисто технически было бы очень сложно сделать компьютер, который бы «понимал» десятичные числа. А вот сделать компьютер, который понимает двоичные числа достаточно легко. Двоичное число оперирует только двумя цифрами – 0 и 1. Несложно сопоставить с этими цифрами два состояния – вЫключено и включено (или нет напряжения –есть напряжение). Процессор – это микросхема с множеством выводов. Если принять, что отсутствие напряжения на выводе – это 0 (ноль), а наличие напряжения на выводе – это 1 (единица), то каждый вывод может работать с одной двоичной цифрой. Сейчас мы говорим о процессоре очень упрощённо, потому что мы изучаем не процессоры, а системы исчисления. Об устройстве процессора вы можете почитать здесь:Структура процессора.

Поляков А.В. Ассемблер для чайников.

35

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

Итак, процессор (и компьютер в целом) использует двоичную систему, которая оперирует всего двумя цифрами: 0 и 1. И поэтому основание двоичной системы равно 2. Аналогично, основание десятичной системы равно 10, так как там используются 10 цифр.

Каждая цифра в двоичном числе называется бит (илиразряд). Четыре бита – этополубайт

(или тетрада), 8 бит –байт, 16 бит –слово, 32 бита –двойное слово. Запомните эти термины, потому что в программировании они используются очень часто. Возможно, вам уже приходилось слышать фразы типаслово данных илибайт данных. Теперь, я надеюсь, вы понимаете, что это такое.

Отсчёт битов в числе начинается с нуля и справа. То есть в двоичном числе самый младший бит (нулевой бит) является крайним справа. Слева находится старший бит. Например, в слове старший бит – это 15-йбит, а в байте –7-й.В конец двоичного числа принято добавлять буквуb. Таким образом вы (и ассемблер) будете знать, что это двоичное число. Например,

101 – это десятичное число

101b – это двоичное число, которое эквивалентно десятичному числу 5.

А теперь попробуем понять, как формируется двоичное число.

Ноль, он и в Африке ноль. Здесь вопросов нет. Но что дальше. А дальше разряды двоичного числа заполняются по мере увеличения этого числа. Для примера рассмотрим тетраду. Тетрада (или полубайт) имеет 4 бита.

Двоичное

Десятичное

Пояснения

0000

0

 

0001

1

В младший бит устанавливается 1.

0010

2

В следующий бит (бит 1) устанавливается 1, предыдущий бит (бит 0) очищается.

0011

3

В младший бит устанавливается 1.

0100

4

В следующий бит (бит 2) устанавливается 1, младшие биты (бит 0 и 1)

 

 

очищаются.

0101

5

В младший бит устанавливается 1.

0110

6

Продолжаем в том же духе.

0111

7

 

1000

8

 

1001

9

 

1010

10

 

1011

11

 

1100

12

 

1101

13

 

1110

14

 

1111

15

 

Поляков А.В. Ассемблер для чайников.

36

Итак, мы видим, что при формировании двоичных чисел разряды числа заполняются нулями и единицами в определённой последовательности:

Если младший равен нулю, то мы записываем туда единицу. Если в младшем бите единица, то мы переносим её в старший бит, а младший бит очищаем. Тот же принцип действует и в десятичной системе:

0…9

10 – очищаем младший разряд, а в старший добавляем 1

Всего для тетрады у нас получилось 16 комбинаций. То есть в тетраду можно записать 16 чисел от 0 до 15. Байт – это уже 256 комбинаций и числа от 0 до 255. Ну и так далее.

На рис. 2.2 показано наглядно представление двоичного числа (двойное слово).

Рис. 2.2. Двоичное число.

2.2.2. Шестнадцатеричная система счисления

Как мы увидели выше, с двоичным числом удобно работать при поразрядных операциях, однако запись двоичного числа получается довольно громоздкой. Чтобы немного упростить жизнь программистам, была придумана шестнадцатеричная система счисления, которая использует 16 цифр:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F

Соответственно, основание шестнадцатеричной системыравно 16.

Шестнадцатеричное число является компактным и лёгким для чтения. Его легко преобразовать в двоичное и наоборот. Каждый разряд шестнадцатеричного числа – это тетрада. Каждую тетраду легко преобразовать в двоичное число и наоборот (см. таблицу

2.3).

Поляков А.В. Ассемблер для чайников.

37

Таблица 2.3. Преобразование чисел.

 

 

 

 

Десятичное

Двоичное

Шестнадцатеричное

 

0

0000

 

0

 

1

0001

 

1

 

2

0010

 

2

 

3

0011

 

3

 

4

0100

 

4

 

5

0101

 

5

 

6

0110

 

6

 

7

0111

 

7

 

8

1000

 

8

 

9

1001

 

9

 

10

1010

 

A

 

11

1011

 

B

 

12

1100

 

C

 

13

1101

 

D

 

14

1110

 

E

 

15

1111

 

F

 

В конец шестнадцатеричного числа принято ставить букву h. Таким образом мы можем отличить шестнадцатеричное число от чисел в других системах исчисления. Например

11 – десятичное число 11

11b – двоичное число, которое эквивалентно десятичному числу 3

11h – шестнадцатеричное число, которое эквивалентно десятичному числу 17

В исходных кодах программ на ассемблере, если шестнадцатеричное число начинается с буквы, то перед ним нужно поставить ноль, иначе ассемблер подумает, что это не число, а имя переменной. Например, число FF в исходном коде на ассемблере должно быть записано как 0FFh.

2.2.3. Другие системы

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

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

Если у вас остались ещё вопросы, то, быть может, вам проще будет разобраться с системами счисления здесь: Системы счисления.

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

Поляков А.В. Ассемблер для чайников.

38

2.3. Представление данных в памяти компьютера

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

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

ВАЖНО!

Здесь мы будем говорить только о представлении данных в компьютерах с процессорами Intel и совместимыми. Представление данных в системах с другими процессорами может отличаться – см. документацию на конкретный процессор.

2.3.1. Положительные числа

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

беззнакового целого двоичного числа, соответствует значению числа 2n.

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

Таблица 2.4. Диапазоны возможных значений положительных чисел.

Тип числа

Диапазон значений

Степени двойки

Байт

0…255

0…(28 – 1)

Слово

0…65 535

0…(216

– 1)

Двойное слово

0…4 294 967 295

0…(232

– 1)

Учетверённое слово

0…18 446 744 073 709 551 615

0…(264

– 1)

Например, максимальное значение, которое может хранить слово данных – это 65 535 или (216 – 1). Почему? Потому что

216 = 65 536 – столько различных чисел может хранить слово данных. Однако сюда же входит число 0, поэтому слово данных может хранить числа от 0 до 65 535. То есть максимальное значение, которое можно записать в слово данных, равно

216 – 1 (число 0) = 65 536 – 1 = 65 535

ВАЖНО!

При работе с числами помните, что в байт можно записать число со значением не более 255, в слово – со значением не более 65 535 и т.д. Поэтому будьте внимательны, особенно при операциях сложения/умножения. Например, если при работе с байтом вы выполните операцию сложения 255 + 1, то в результате должно получиться число 256. Однако если вы запишите результат в байт, то, к вашему удивлению, результатом будет не 256, а 0. Об этом подробнее мы будем говорить в разделе о переполнении.

Поляков А.В. Ассемблер для чайников.

39

2.3.2. Отрицательные числа

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

Для того чтобы указать знак числа, достаточно одного разряда (бита). Обычно знаковый бит занимает старший разряд числа. Если старший бит числа равен 0, то число считается положительным. Если старший разряд числа равен 1, то число считается отрицательным. Пример байта со знаком приведён на рис. 2.3.

Разряды

 

 

 

 

 

Число

7

6

5

4

3

2

1

0

 

1

0

0

1

0

0

1

0

–110

0

1

1

0

1

1

1

0

+110

Рис. 2.3. Отрицательное число в памяти компьютера.

Как вы успели заметить, для представления числа со знаком требуется использовать старший бит для определения знака числа. Это означает, что этот старший бит уже нельзя использовать для записи самого числа, то есть максимальное значение, которое мы сможем записать в байт, будет уже не 255, а всего 127. Диапазоны возможных значений чисел со знаком приведены в таблице 2.5.

Таблица 2.5. Диапазоны возможных значений чисел со знаком.

Тип числа

Диапазон значений

Степени двойки

Байт

–128…+127

–27…(27 – 1)

Слово

–32768…+32 767

–215…(215

– 1)

Двойное слово

–2147 483 648…+2 147 483 647

–231…(231

– 1)

Учетверённое слово

–9223 372 036 854 775 808…

–263…(263

– 1)

 

+9 223 372 036 854 775 807

 

 

А теперь разберёмся с загадочной операцией дополнение до двух. Для изменения знака числа выполняетсяинверсия, то есть для числа в двоичном представлении все нули заменяются единицами, а все единицы – нулями. Затем к полученному результату прибавляют 1. Возьмём, например, десятичное число 110 (в двоичной системе это число

01101110). Тогда

Исходное число

0110

1110

Инверсия

1001

0001

Прибавляем 1

1001

0010

Как видим, после выполнения этих преобразований в старшем разряде у нас 1, то есть число отрицательное. А теперь проверим, что это число действительно отрицательное. Как это сделать? Вспомним, что (–110+ 110 = 0). То есть сложение полученных нами двоичных чисел тоже должно дать в результате ноль. Итак

01101110

+

10010010

=

100000000

Поляков А.В. Ассемблер для чайников.

40

То есть у нас получилось девятиразрядное число 100000000 (десятичное 256). Однако мы работаем с байтом, а в байте, как известно, только 8 бит (от 0 до 7). То есть единица у нас перешла в 8-йбит, которого в байте попросту нет. То есть для байта это эквивалентно числу

0.

В некоторых источниках дополнение до двух носит название двоичный дополнительный код.

Подведём итоги.

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

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

Преобразования положительного двоичного числа со знаком (в старшем бите 0) в десятичное число выполняется также как и для чисел без знака.

Преобразование отрицательного двоичного числа (в старшем бите 1) в десятичное число выполняется путём нахождения его дополнительного кода. То есть для двоичного числа 10010010 операция будет следующей:

Исходное число

1001

0010

Инверсия

0110

1101

Прибавляем 1

0110

1110

В итоге получаем число 110, но поскольку в исходном числе старший бит был равен 1, то это отрицательное число, то есть –110.

2.3.3. Что такое переполнение

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

01101110

+

01101110

=

11011100

Или в десятичной системе 110 + 110 = 220. Но мы то работаем с числами со знаком. В этом случае максимальное значение для байта равно 127. А полученное нами двоичное число будет на самом деле отрицательным числом –36(см. разделОтрицательные числа). В случае переполнения устанавливается флаг OF в регистре флагов (см.следующий раздел).

Вернёмся к примеру сложения двух чисел:

01101110

+

10010010

=

100000000

studfiles.net

Assembler, язык программирования ассемблер; программирование на ассемблере.

Здесь мы размещаем статьи и шпаргалки, посвященные языку программирования Assembler (ассемблер). А также примеры на ассемблере, описание команд ассемблера. Любой сможет тут найти уроки и прочую полезную информацию по ассемблеру для начинающих. Для правильного изучения языка программирования assembler рекомендуем воспользоваться оглавлением.

Первая программа на языке C#

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

Для написания C# кода можно использовать простой текстовый редактор (практически любой на ваш выбор), например, встроенный в OS Windows, блокнот. Или же более продвинутый, с точки зрения функциональности, NotePad++. Однако, намного удобнее разрабатывать программы (как маленькие, так и очень большие) в так называемой среде разработки.

Ассемблер для начинающих. Оглавление.

Список статей, посвященных ассемблеру в верном для изучения порядке. Статьи предназначаются как для начинающих изучать assembler (ассемблер для чайников), так и для опытных программистов. Программная модель микропроцессора IA-32. Режимы работы микропроцессора IA-32. Организация памяти Регистры процессора Структура оператора и псевдооператора Типы данных, с которыми работает процессор Директивы определения переменных Директивы определения констант Директивы определения сегментов,[…]

24. Команды работы со стеком

Для организации работы со стеком существуют специальные команды записи и чтения: Команда PUSH выполняет запись значения «источник» в вершину стека: PUSH источник Алгоритм работы этой команды, включает два действия: Значение SP уменьшается на 2 Значение источника записывается по адресу, указываемому парой SS:SP. Команда POP выполняет запись значения из вершины стека по месту, указанному операндом «приемник»[…]

2. Организация памяти

Физическая память, к которой процессор имеет доступ по шине адреса называется оперативной памятью. На самом нижнем уровне памяти она представлена в виде массива битов. Минимальная адресуемая ячейка памяти — байт. Оперативная память — это последовательность байтов. Также процессор работает со словами и двойными словами (слово — 2 байта / 16 бит, двойное слово — 4[…]

23. Принцип организации стека

Стек – это область памяти, специально выделяемая для временного хранения данных программы. Важность стека определяется тем, что для него в структуре программы предусмотрен отдельный сегмент. Для работы со стеком предназначены три регистра: ss – сегментный регистр стека; sp/esp – регистр указателя стека; bp/ebp – регистр указателя базы кадра стека. Размер стека зависит от режима работы[…]

18. Команды условной передачи управления

Команды условного перехода имеют следующий синтаксис: jcc метка_перехода Межсегментная передача управления в условных переходах не допускается. Команды, позволяющие сформировать условие перехода Арифметические Команда СMP Проверка флагов Проверка регистра CS Команда cmp также, как и команда sub, выполняет вычитание операндов и устанавливает флаги. Единственное, чего она не делает — это запись результата вычитания на место первого[…]

11. Арифметические команды.

Арифметические команды делятся на 2 группы: Двоичной арифметики. Десятиной арифметики. Все арифметические команды изменяют флаги состояний CF, ZF, SF, AF, OF. Команды двоичной арифметики: инкремент/декремент (увеличение/уменьшение операнда на 1) INC/DEC регистр/память сложение/вычитание ADD/SUB получатель, источник меняет знак операнда на противоположный. NEG регистр/память сложение/вычитание дополнительно прибавляет/вычитает от результат флаг CF ADC/SBB получатель, источник умножение беззнаковое/умножение знаковое[…]

35. Макродирективы повторения, управления процессом генерации, отображения сообщений во время макрогенерации.

В языке ассемблера предусмотрены несколько циклических директив, предназначенных для генерации повторяющихся блоков операторов: WHILE, REPEAT, IRP и IRPC. В отличие от команды LOOP, эти директивы работают только во время компиляции программы, причем в качестве счетчика и условия завершения цикла выступают константные выражения. WHILE константное_выражение Позволяет повторить некоторый блок операторов в зависимости от значения указанного в[…]

33. Параметры макрокоманды и макроопределения. Макрофункция

Обычно макрокоманда содержит некоторый список аргументов — список_фактических_аргументов, которыми корректируется макроопределение. Места в теле макроопределения, которые будут замещаться фактическими аргументами из макрокоманды, обозначаются с помощью так называемых формальных аргументов. Таким образом, в результате применения макрокоманды в программе формальные аргументы в макроопределении замещаются соответствующими фактическими аргументами; в этом и заключается учет контекста. Процесс такого замещения называется[…]

32. Макросредства. Макроопределение, макрокоманда, макрорасширение.

Макроопределение – специальным образом оформленная группа команд, к которой в тексте программы можно обратиться с помощью некоторого символического имени – макрокоманды. (макроопределение может иметь формальные параметры, тогда макрокоманда должна иметь фактические). Макрорасширение – некоторая последовательность инструкций ассемблера, которую формирует макроассемблер на этапе трансляции, путем замены формальных параметров макроопределения фактическими параметрами макрокоманды. Полученное макрорасширение вставляется в[…]

indigobits.com

Дневники чайника

Дневники чайника

— Так кто вы всё-таки будете?
— Асм есть Царь!
(Из кинофильма «Иван Васильевич меняет профессию»)

Благодарность

Я действительно благодарен всем моим читателям, особенно активным, вы мне очень помогли. Если бы не вы, этих уроков не было бы.

Также уроков могло не быть без Плохиша (Bad_guy, извини, что так назвал :). Он посадил зерно crackl@b’a на просторы инета и ухаживал за ним все эти годы, пока проект превращался в дерево знаний. Спасибо zer0 за управление разделом статей.

Спасибо всем участникам нашего форума и «wasm.ru/forum» за помощь и науку, особенно: Leo, S_T_A_S_,Staier, The Svin.

Ну и, конечно, отдельное спасибо Седому (SeDoYHg или SeDoY) за огромную помощь в написании Чтивы 0 и за критику первых статей. Я даже могу сказать, что почти все главы здесь под редакцией Седого.

Да, чуть не забыл, без моей мамы текст был бы полон «обшибак и слеганца бесграматен» :).

А без содействия папы вообще бы не стал заниматься Ассемблером (в бизнес бы ударился, стал бы авторитетом, шлёпнули бы где-нибудь у входа в казино — и контрольный выстрел… А так максимум, что светит, — это потёртые данные на винте и радикулит :).

Короче говоря, всем, кто помог, — спасибо.

Пустословие

Как был предусмотрителен Джордж Лукас, когда снял 4-й эпизод «Звёздных Войн». Я понятия не имел, что возникнет потребность написать предчасть. А вот пришлось. После того, как я написал «Чтиву III», прошло 4 месяца.

Дело в том, что первая часть начинается примерно c такой фразы: «Прочтите Рассылку Калашникова и возвращайтесь читать Дневники чайника». Сам дочитал эту рассылку только до десятого урока, дальше идёт морально устаревшая информация.

Надеюсь, что большинство из тех, кто созрел для Асма, поймёт мой рассказ (от 9 до 110 лет :). Если не поймёте, не отчаивайтесь, есть другие дороги. Давно существуют подобные курсы элементарного ликбеза, например:

  • Уже упомянутая рассылка Олега Калашникова «Ассемблер? Это просто!» (устарела, зато сразу практика). Кстати, эта же рассылка на всякий случай лежит и здесь, на Краклабе.
  • «Низкоуровневое программирование для дZенствующих». Сейчас считаю, что это хорошая дорога для начинающих, но когда сам ничего не знал, эти статьи мне не понравились. Решайте сами, подойдут ли они вам сразу. На том же сайте вы найдёте море материала по теме. Искренне благодарен всем, кто трудится над этим ресурсом.
  • Советую в первую очередь обратить внимание на статьи Кибер Маньяка (CyberManiac) из серии «Теоретические основы крэкинга» в разделе статей здесь на Краклабе или на Wasm’e в этом разделе.

В любом случае советую прочесть все известные уроки. В каждом источнике автор по-своему раскладывает тему. Есть много мнений о том, какие аспекты самые важные, и каждая точка зрения для новичка — золото. Остальные интересные ссылки я уже поместил в следующих статьях, так что если вы пожелаете сначала завалиться литературой, а потом разгребать её, можете смело смотреть Чтиву 1,2,3.

Для кого пишу

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

Совсм недавно не было никакого Битфрая, я вообще был далёк от программирования. Конечно, проводил много времени за компом и стал толковым юзверем, но я не знаю математики, даже на уровне школы. Год назад я совсем не представлял, что такое написать программу.

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

Хотя вру, такую точку зрения поддерживают некоторые уважаемые люди. Но явной мысли «начинать надо с Асма» нигде так и не увидил.

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

Print  "Здесь был Вася"

В Ассемблере нет оператора «PRINT» и нет даже его подобия. Этот язык может показаться вам странным (как мне другие), если вы привыкли к логике высокоуровневых языков.

В данной статье за главный объект изучения будет принят язык Ассемблер для Intel-совместимых процессоров.

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

Возможно, кто-то из вас сразу же предпочтёт прочитать большой учебник. Например:
В.И. Юров
«ASSEMBLER. 2-е издание. Учебник для вузов»
и учебник Зубкова в качестве интересных примеров для программирования (на форуме есть ссылки).

Не нужно искать в моей статье глубокие тайны программирования, и уж совсем не стоит считать Чтиву 0 истиной в последней инстанции.

Но если вы любите обрастать знаниями по ходу экспериментов (как Bitfry), добро пожаловать в мир ассемблера через мою «калитку».

Метод обучения

«Чтива 0» имеет мало общего со своими предками (Чтивы I,II,III), хотя бы потому, что это не мой дневник. Скорее, «Чтива 0» будет Ваш дневник, Ваши ошибки и Ваши уроки ;).

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

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

Человеку для первого, невооружённого, осмотра местности, лучше думать, что земля плоская (поверьте, так будет лучше). Затем он осваивает всё больше и больше, а в какой-то момент до него вдруг доходит: чтобы сложить карты и сопоставить с положением звёзд на небе, нужно представить невероятное — земля, оказывается, шар. Но и это не есть истина, на самом деле земля очень сложной формы, и чтобы описать её более-менее точно, нужно использовать все ресурсы науки и техники. Конца этому процессу не предвидится. То же самое можно сказать и о компьютере. Несмотря на то, что он всего лишь юное творение человека, мы умудрились запутать в нём столько всяких абстракций (которые ему, кстати, мешают), что Ассемблер можно уже воспринимать как насмешку над корнем этого слова.

Сделаю всё возможное, чтоб избежать сложных понятий, также обещаю не допускать тупостей вроде «земля круглая», так как это больше всего сбивает с толку, уж лучше думать, что она плоская, чем круглая :), по крайней мере, я буду стараться так не писать.

Но вернёмся к виткам познаний. В Чтиве 0 мы с вами постараемся смоделировать два таких витка (пока мне так кажется, может быть, их будет больше).

Нулевой виток будет содержать много практики и некоторое количество утверждений.

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

Таким образом, обе части нулевой чтивы будут иметь одинаковые темы глав.


Вступление в суть                               День первый
Системы счисления и устройство памяти           День второй
Регистры процессора                             День третий
Практикация всего мозга                         День четвёртый
О словах и двойных словах (форматы данных)      День пятый
Циклы, ветвления и регистр Флагов               День шестой
Знакомство с Win32-программированием            День седьмой
Стек                                            День восьмой
Структурирование программы                      День девятый

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

Статья получилась длинная и пёстрая, поэтому вам лучше сразу знать что как будет выглядеть. Кроме основного текста, вы здесь встретите:

Выделения, как обычно — суть из массы

— Сноски в конце главы

Код программ
Код исходников программ

Действия примера

Cравка о командах процессора

Ну и в этих серых блоках будет развлекуха, её читать совсем необязательно, поэтому с неё и начнём :).

Эй, малыш! Да, ты… Можешь раздобыть некоторый скарб для моего корабля?…

Инструменты, которые нам пригодятся

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

Перед отправлением в дальний поход необходимо как следует проверить укомплектованность нашего космического корабля.

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

Для начала посмотрите приложенные файлы: need.rar, prax0.rar, prax1.rar, общий размер ~500Kb. Там лежат примеры для проверки их работоспособности и кое-что ещё.

Hiew

Сайт программы, размер ~0,5Mb. Программа платная.

Версия должна быть для форточек не ниже 6.8 (я использую 7.01).

Если у вас нет этой программы, то в сети вы без проблем найдете её.

Heiw — это консольный шестнадцатиричный редактор с возможностью ассемблировать/дизассемблировать. Незаменимая для исследователей и ассемблерщиков вещь.

FAR manager

Сайт программы, размер ~3Mb. Программа бесплатная для русскоязычных пользователей.

Подойдёт и новая x64-версия 2.0 и 32-битная. Короче – любая. Порекомендовал бы использовать именно FAR, так как он тоже консольный. Сам я пользуюсь двумя файловыми менеджерами: Total Commander и Far. По опыту могу сказать, что Far можно настроить по сочетанию клавиш один в один с TC, было бы желание. Внешний вид настраивается до мелочей, просто на это надо потратить некоторое время. Far будет приятным и удобным если вы этого захотите, поверьте. Меня, например, дико раздражают мелкие шрифты и кислотные краски стандартной консоли (что Hiew, что Far, что любая другая цветная консольная программа), однако, всегда можно создать ярлычок в котором будут настройки шрифтов и палитра приятная для глаза. Ярлык для Far’a с моими любимыми цветами я прикрепил в файл need.rar. Кроме того можно настроить цветовую схему. Hiew и Far имеют богатые возможности в этом плане. Пробуйте. Однако если вам совсем не нравятся консоли, можете использовать что-то типа TC или обычный проводник.

CodeView (CV)

Сайт программы: microsoft.com. В принципе программа доступна для бесплатного скачивания где-то в дебрях Майкрософта, однако она является лишь придатком к довольно большому ненужному пакету, который входит в дополнение (не помню к чему). Отыскать её там будет непросто. Я выложил эту довольно старую программу у себя (в том же архиве need.rar).

Ещё CV входит в старый MASM (v5x,v6x) который входит в VisualC++ (версии не знаю).

CodeView — программа-отладчик (по-ихнему debugger — исправлятель ошибок). Отладчики помогают программистам понять, что делает их программа. 🙂 Когда этот светлый миг наступает, становится понятно, где ошибка.

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

OllyDbg

Сайт программы, размер ~1Mb. Программой можно пользоваться бесплатно с разрешения автора.

На 07.12.2011 последняя версия Oлли — 2.01 alpha 4, но можно использовать и старую стабильную 1.10.

А вот этот отладчик на сегодняшний день самый актуальный на платформах вплоть до Win7 x64 на уровне 32-битных приложений. OllyDbg — самый многофункциональный отладчик прикладных программ Win32. Но как только появится хороший подходящий для нас отладчик x64, сразу возьмусь переписывать уроки под него.

MASM32 SDK

Сайт программы, размер ~4Mb. Программа бесплатная.

Проект Стива Хатчисона (Steve Hutchesson). MASM32 – это современный пакет языка Ассемблер, собранный на основе компилятора MicroSoft.

Существует ещё пакет MASM (Macro Assembler) — это древний DOS’овый пакет от самой MS. Нам он не нужен, так же как и NASM, TASM, TASM32 и т.д.

На сегодняшний день единственной разумной альтернативой MASM32 является FASM. Сам я использую и FASM, и MASM32, но тему FASM’a затрагивать пока не будем.

Что такое «пакет языка Ассемблер»?

В стандартный пакет языка программирования входят:

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

Всё это нам понадобится не сразу, а постепенно, по мере необходимости. Поэтому не бросайтесь сейчас же изучать и осваивать все вышеперечисленные приборы. Однако Hiew и CodeView нужны будут сразу же после вылета с базовой станции.

На Windows версии x64 (7/Vista/XP или Server) в первые дни вам понадобится какой-нибудь эмулятор DOS-режима для запуска com-программ. Можно использовать громоздкий Virtual PC от MS или VMWare, но я предлагаю (спасибо Григорию за подсказку) маленький удобный эмулятор:

DOSbox

Сайт программы, размер ~1,5Mb. Программа бесплатная.

Без этой программы можно обойтись на 32-битной WinXP. На Висте и Семёрке x86 лично не проверял, но говорят, можно обойтись режимом совместимости (пробуйте и отпишитесь в гостевой по результатам).

Не смущайтесь, что версия называется «Win32 installer», она поможет и на системе x86, и на x64 эмулировать режим старой-доброй DOS для наших первых примеров. DOSbox устанавливается за пару секунд, и его очень легко настроить. Нужно всего лишь смонтировать папку с com-примерами и туда же кинуть все файлы отладчика CV. Монтаж выполняется одной командой. Например:

mount с d:\prax

где «d:\prax » – это папка на реальном диске D, в которой должны быть свалены воедино ваши com-примеры и файлы отладчика CV. А «c» – это уже виртуальный диск внутри dosbox’a.

Далее переходим на новый виртуальный диск командой

с:

Что потом – читайте уже в следующей главе. Можно, кстати, батничек сделать… Разумеется, надо знать основы языка команд DOS и DOSbox (на сайте программы есть русская документация). Сразу рекомендую главу специально для пользователей, впервые очутившихся в DOS-мире.

Инструменты, которые нам НЕ пригодятся.

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

Кажется, можно отправляться.

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

Можно сравнить эту часть с детским мультиком — все бегают-прыгают, яркие картинки, сплошные перегибы и упрощения.

Bitfry


bitfry.narod.ru

MASM, TASM и WASM

Главная / Ассемблер / Для чайников / Быстрый старт /

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

Итак, наша первая программа для MASM, TASM и WASM, которая выводит английскую букву «A» в текущей позиции курсора, то есть в левом верхнем углу экрана:


       .model tiny
       .code
       ORG    100h
start: MOV    AH,2
       MOV    DL,41h
       INT    21h
       INT    20h
       END    start
Этот текст можно набрать в любом простом текстовом редакторе – например в БЛОКНОТЕ (NotePad) от WINDOWS (но не в Word и не в другом «навороченном»). Однако я рекомендую «продвинутый» текстовый редактор с подсветкой синтаксиса, например, PSPad (см. раздел ВВЕДЕНИЕ). Затем сохраняем этот файл с расширением .asm, например, в папке MYPROG. Назовем файл atest. Итак, мы получили: C:\MYPROG\atest.asm.

ПРИМЕЧАНИЕ
Обратите внимание, что в первой команде мы записали 2 вместо 02h. MASM, TASM и WASM, как и Emu8086, допускают такие «вольности». Хотя можно написать 02h – ошибки не будет.

Пояснения к программе:

.model tiny – 1-ая строка. Директива .model определяет модель памяти для конкретного типа файлов. В нашем случае это файл с расширением COM, поэтому выбираем модель tiny, в которой объединены сегменты кода, данных, и стека. Модель tiny предназначена для создания файлов типа СОМ.

.code – 2-ая строка. Эта директива начинает сегмент кода.

ORG 100h – 3-ая строка. Эта команда устанавливает значение программного счетчика в 100h, потому что при загрузке СОМ-файла в память, DOS выделяет под блок данных PSP первые 256 байт (десятичное число 256 равно шестнадцатеричному 100h). Код программы располагается только после этого блока. Все программы, которые компилируются в файлы типа СОМ, должны начинаться с этой директивы.

start: MOV AH, 02h – 4-я строка. Метка start располагается перед первой командой в программе и будет использоваться в директиве END, чтобы указать, с какой команды начинается программа. Инструкция MOV помещает значение второго операнда в первый операнд. То есть значение 02h помещается в регистр АН. Для чего это делается? 02h — это ДОСовская функция, которая выводит символ на экран. Мы пишем программу для DOS, поэтому используем команды этой операционной системы (ОС). А записываем мы эту функцию (а точнее ее номер) именно в регистр АН, потому что прерывание 21h использует именно этот регистр.

MOV DL, 41h – 5-я строка. Код символа «A» заносится в регистр DL. Код символа «A» по стандарту ASCII – это число 41h.

INT 21h – 6-я строка. Это и есть то самое прерывание 21h – команда, которая вызывает системную функцию DOS, заданную в регистре АН (в нашем примере это функция 02h). Команда INT 21h – основное средство взаимодействия программ с ОС.

INT 20h – 7-я строка. Это прерывание, которое сообщает операционной системе о выходе из программы, и о передаче управления консольному приложению. В том случае, если программа уже откомпилирована и запущена из ОС, команда INT 20h вернет нас в ОС (например, в DOS).

END start – 8-я строка. Директива END завершает программу, одновременно указывая, с какой метки должно начинаться ее выполнение.

Ну вот, программу мы написали. Но хотелось бы посмотреть, как она работает. Для этого нужно сначала вызвать ассемблер, чтобы скомпилировать ее в объектный файл, а затем вызвать компоновщик, который из объектного файла создаст исполняемый файл, то есть программу типа COM. Для разных ассемблеров придётся выполнять эти действия по разному.


av-assembler.ru

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *