|
Основы программирования на ассемблере |
| Содержание | <<< | >>> |
Регистры CPU
|
| адрес | ячейка |
| 0000:0000 | 8A |
| 0000:0001 | 10 |
| 0000:0002 | 1C |
| ... | ... |
| 0ABD:0100 | 04 |
| 0ABD:0101 | 8B |
| 0ABD:0102 | 00 |
| ... | ... |
| FFFF:FFFD | 00 |
| FFFF:FFFE | 00 |
| FFFF:FFFF | 00 |
Рассмотрим структуру оперативной памяти, и определим место для хранения инструкции сложения регистров AX и BX.
ОЗУ состоит из множества упорядоченных, однобайтовых ячеек. Каждая ячейка
имеет уникальный номер (адрес).
Адрес ячейки состоит из двух частей:
0ABD:0100 - полный адрес 0ABD - сегмент 0100 - смещение 0000:0000 - первый адрес ОЗУ FFFF:FFFF - последний адрес ОЗУCовременные системы программирования полностью исключают понятие сегментации, и позволяют работать с памятью, как с непрерывным массивом. Но базовые элементы языка Ассемблер во многом опираются на рассмотренную модель памяти.
Область ОЗУ [0000:0000...0ABD:0000] заполнена различными программами,
трогать данный раздел не рекомендуется. Начиная с адреса 0ABD:0100 можно
писать свои инструкции. Этот адрес хранится в регистрах специального назначения
CPU:
DS=0ABD, ES=0ABD, SS=0ABD, CS=0ABD и IP=0100.
Для записи в ОЗУ кодов инструкции сложения AX + BX, воспользуемся командой "E" (Edit):
-e 100 <Enter> 0ABD:0100 04.01 <Enter> -e 101 <Enter> 0ABD:0101 8B.D8 <Enter>Запишите в регистры следующие числа: AX = 4, BX = 3. Просмотрите регистры:
-r AX=0004 BX=0003 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0ABD ES=0ABD SS=0ABD CS=0ABD IP=0100 NV UP EI PL NZ AC PO NC 0ABD:0100 01D8 ADD AX,BXВ третьей строке листинга находится следующая информация:
0ABD:0100 - адрес инструкции сложения 01D8 - коды инструкции ADD AX,BX - мнемокод инструкцииМнемокод служит для наглядного восприятия инструкций CPU.
Теперь все готово для выполнения операции сложения. Команда "T" (Trace) дает указание микропроцессору трассировать (выполнить) одну инструкцию:
-t AX=0007 BX=0003 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0ABD ES=0ABD SS=0ABD CS=0ABD IP=0102 NV UP EI PL NZ AC PO NC 0ABD:0102 00E8 ADD AL,CHМикропроцессор выполнил сложение AX + BX и занес результат в регистр AX. Теперь в третьей строке находится адрес и мнемокод следующей инструкции. Откуда она взялась? Это фрагмент программы или данных, которые потеряли свою актуальность до загрузки Debug.
Также изменил свое значение регистр IP = 0102 (было 0100). IP (Instruction Point) - указывает на инструкцию, которую должен выполнить CPU. Верните IP в исходное состояние:
-r ip IP=0102 :100Вновь просмотрите регистры:
-r AX=0007 BX=0003 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0ABD ES=0ABD SS=0ABD CS=0ABD IP=0100 NV UP EI PL NZ AC PO NC 0ABD:0100 01D8 ADD AX,BXВыполните трассировку, и убедитесь, что AX = 000A: 7h + 3h = Ah. Обратите внимание, что коды инструкции ADD AX, BX постоянно остаются в памяти. Для трассировки инструкции, необходимо указывать в регистре IP ее адрес (в данном случае IP = 100).
1. 0100 + 0F00 3. 00FF + 0001 5. 0123 + 0235 2. F03E + 01E8 4. 98A4 + 493E 6. 0E8F + 0111(результаты вычислений можете проверить сложением в "столбик")
-e 100 <Enter> 0ABD:0100 01.29 <Enter> -e 101 <Enter> 0ABD:0101 D8.D8 <Enter>Запишите в регистры следующие числа: AX = F, BX = B, IP = 100. Просмотрите регистры:
-r AX=000F BX=000B CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0ABD ES=0ABD SS=0ABD CS=0ABD IP=0100 NV UP EI PL NZ AC PO NC 0ABD:0100 29D8 SUB AX,BXВыполните трассировку инструкции. Результат операции смотрите в регистре AX.
Используя инструкцию SUB, выполните следующие действия:
1. 012F - 012E 3. F345 - 0045 5. 0BC1 - 0AC0 2. 0983 - 0873 4. FB32 - AD8C 6. 1000 - 0001Проверим, как CPU ведет себя с отрицательными числами. Для этого выполним вычитание 0 - 1, и посмотрим, получится ли FFFFh. Установите AX = 0, BX = 1 и выполните вычитание. Вероятно, вы получили то, что ожидали: AX = FFFFh.
Если AX = 3EF8, то AH = 3E и AL = F8
При делении шестнадцатибитного регистра AX на две части, получается
два независимых восьмибитных регистра, в каждом из которых можно хранить
один байт. По этой причине такие регистры называют байтовыми.
Существуют инструкции для работы с байтовыми регистрами, например:
ADD AH,AL (код операции: 00h, C4h)
Занесите в память компьютера коды операции сложения AH + AL:
-e 100 <Enter> 0ABD:0100 29.00 <Enter> -e 101 <Enter> 0ABD:0101 D8.C4 <Enter>Занесите в регистры следующие числа: AH = 01, AL = 03. К сожалению Debug не позволяет использовать команду "R" для записи чисел в регистры AH и AL, поэтому числа придется заносить парой:
-r ax AX=0000 :0103Установите IP = 100 и выполните трассировку. Результат сложения смотрите в регистре AH:
-t AX=0403 BX=000B CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0ABD ES=0ABD SS=0ABD CS=0ABD IP=0102 NV UP EI PL NZ NA PO NC 0ABD:0102 00E8 ADD AL,CHИспользуя регистры AH и AL, выполните следующие действия:
1. 7F + 01 3. A4 + B5 5. 98 + 08 2. BE + 0F 4. 14 + D9 6. FF + 01
Рассмотрим умножение двух максимальных по размеру чисел, которые можно записать в регистр: FFFFh ? FFFFh = FFFE0001h
Такое 32-битное число в регистр не поместится. Поэтому, результат операции умножения заносится в регистровую пару [DX:AX]: DX=FFFE, AX=0001.
Введите коды F7h и E3h по адресам 100h и 101h. Установите AX=FFFFh, BX=FFFFh и IP=100. Просмотрите регистры. В листинге регистров инструкция умножения выглядит так: MUL BX. Мнемокод инструкции не содержит регистр AX. Микропроцессор всегда умножает регистр указанный в инструкции, на регистр AX, и сохраняет результат в регистровой паре [DX:AX]. Самостоятельно завершите умножение.
Умножение чисел можно выполнять и с другими регистрами общего назначения, например: MUL CX. Но результат всегда сохраняется в регистровой паре [DX:AX].
| DX - старшая часть делимого
AX - младшая часть делимого BX - делитель |
![]() |
? | DIV BX |
Результат деления заносится в регистры AX и DX:
AX - целая часть результата
DX - остаток от деления
Например, выполним деление 7С4B12h / 100h:
1. 0FEFh x 0100h 3. 543Fh x 32CEh 5. 1000h / 0100h 2. 12E8h x 1AD7h 4. 0FE8h / 0100h 6. FFFFh / 00FFh
| Содержание | <<< | >>> |