17. 32-разрядная архитектура. 17.1. Регистры ЦП

Лекции по предмету «Информатика»
Информация о работе
  • Тема: 17. 32-разрядная архитектура. 17.1. Регистры ЦП
  • Количество скачиваний: 2
  • Тип: Лекции
  • Предмет: Информатика
  • Количество страниц: 12
  • Язык работы: Русский язык
  • Дата загрузки: 2014-05-05 16:23:21
  • Размер файла: 34.46 кб
Помогла работа? Поделись ссылкой
Ссылка на страницу (выберите нужный вариант)
  • 17. 32-разрядная архитектура. 17.1. Регистры ЦП [Электронный ресурс]. – URL: https://www.sesiya.ru/lekcii/informatika/17-32-razryadnaya-arhitektura-171-registry-cp/ (дата обращения: 12.05.2021).
  • 17. 32-разрядная архитектура. 17.1. Регистры ЦП // https://www.sesiya.ru/lekcii/informatika/17-32-razryadnaya-arhitektura-171-registry-cp/.
Есть ненужная работа?

Добавь её на сайт, помоги студентам и школьникам выполнять работы самостоятельно

добавить работу
Обратиться за помощью в подготовке работы

Заполнение формы не обязывает Вас к заказу

Информация о документе

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

Если Вы являетесь автором текста представленного на данной странице и не хотите чтобы он был размешён на нашем сайте напишите об этом перейдя по ссылке: «Правообладателям»

Можно ли скачать документ с работой

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

17. 32-разрядная архитектура.
17.1. Регистры ЦП.
Процессоры 8086 — 80286 за одну операцию могли обработать только 8- или 16-разрядный операнд. Для обработки операндов большего размера приходится писать программы из нескольких команд. Начиная с процессора 80386, появившегося в 1985 г., операнды стали 32-разрядными. За счет этого увеличивается скорость обработки данных. Появилась возможность адресовать большие объемы памяти.
В программной модели процессора наибольшую роль играют регистры. Начиная с 386-го процессора, они делятся на две группы: прикладные и системные регистры.
Прикладные регистры.
HL- и PI-регистры стали 32-разрядными. При этом осталась возможность обращаться к их младшим словам. Непосредственного доступа к старшим словам нет. Чтобы получить содержимое старшего слова регистра, нужно сдвинуть содержимое регистра вправо на 16 бит. (Соответствующие команды мы скоро изучим.). К прежним названиям регистров добавлен префикс E — Extended (расширенный).
31 15 7 0
EAX AH AL AX
EBX BH BL BX
ECX CH CL CX
EDX DH DL DX
Рис.1. HL-регистры
31 15 0
ESI SI
EDI DI
ESP SP
EBP BP
Рис.2. PI-регистры
К прежним сегментным регистрам добавились два новых: FS и GS. Они служат для адресации сегментов данных (как DS и ES). Разрядность сегментных регистров не изменилась.
15 0
CS
DS
SS
ES
FS
GS
Рис.3. Сегментные регистры
Стали 32-разрядными EIP — счетчик команд и EFLAGS — регистр флагов. В EFLAGS появились новые флаги. Изучать эти флаги мы не будем, т.к. они представляют интерес лишь для разработчиков операционных систем.
Вызывает разочарование, что количество регистров общего назначения не увеличилось, увеличена только разрядность самих регистров.
Системные регистры перечислим формально, так как парой слов об их назначении не отделаешься. Их состав различен для разных моделей. Покажем их для Pentium.
управляющие регистры (control registers) CR0 — CR4 (CR1 зарезервирован);
отладочные регистры (debug registers) DR0 — DR7;
тестовые регистры (test registers) TR6,TR7;
регистры таблиц дескрипторов GDTR, IDTR, LDTR;
регистр задачи (task register) TR.
Эти регистры нужны при создании операционных систем и таких утилит, как отладчики.

17.2. Методы адресации.
Теперь эффективный адрес можно вычислить не только по формуле, приводившейся ранее (где в число базовых входили только BX и BP, а в число индексных SI и DI, причем разница между ними была не вполне понятна (например, невозможна была команда mov ax, [si+di]), но и по новой формуле, включающей только 32-разрядные регистры:
база + индекс*коэффициент + смещение.
Расшифруем это более подробно

В число индексных регистров не входит ESP, а смещение (displacement) не может быть 16-разрядным. Разумеется, умножение индексного регистра на 1 можно не записывать явно. Обратите внимание, что команда mov [ax],bx по-прежнему недопустима.
В следующем очень простом примере мы увидим, как оформлять программы на языке Ассемблера при использовании возможностей 386-го процессора.
Пример. Сумма двух 32-разрядных чисел.
файл add32.asm:
.MODEL small
.386
.STACK 100h
.DATA
sum DD 0
.CODE
start: mov ax,@data
mov ds,ax
mov eax,12345678h
add eax,87654321h
mov sum,eax
mov ax, 4C00h
int 21h
END start
В программе имеется директива .386. Она необходима, так как в программе присутствуют 32-разрядные регистры. Трансляция и компоновка осуществляются командами:
tasm /zi/l add32.asm
tlink /v/3 add32.obj
Здесь присутствует новая для нас опция компоновщика /3 — Enable 32-bit processing (поддержка 32-битового кода).
Упражнение. Закомментируем директиву .386. Реакция tasm:
**Error** add32.asm(9) Undefined symbol: EAX
*Warning* add32.asm(9) Argument needs type override
tasm не распознает EAX.
Восстановим директиву .386 и проведем компоновку без ключа /3. Реакция tlink:
Fatal: Bad object file record in add32.asm near module file offset 0x00000000
Теперь вызовем отладчик
td add32.exe
Откроем окно кода (F10/View/CPU), распахнем его во весь экран (F5), перейдем в панель регистров (TAB) и вызовем контекстное меню (Alt+F10).
Increment
Decrement
Zero
Change...
Registers 32-bit No
Выберем последний пункт меню. Панель регистров приобретет вид:
eax 00000000
ebx 00000000
ecx 00000000
edx 00000000
esi 00000000
edi 00000000
ebp 00000000
esp 00000100
ds 1927
es 1927
fs 0000
gs 0000
ss 193A
cs 1937
ip 0000
Теперь в этой панели отображаются 32-разрядные регистры. Прогон по шагам делаем обычным образом (F7)
Посмотрим листинг программы (удалены заголовок и таблица символов)
1 0000 .MODEL small
2 .386
3 0000 .STACK 100h
4 0000 .DATA
5 0000 00000000 sum DD 0
6 0004 .CODE
7 0000 B8 0000s start:mov ax,@data
8 0003 8E D8 mov ds,ax
9 0005 66| B8 12345678 mov eax,12345678h
10 000B 66| 05 87654321 add eax,87654321h
11 0011 66| A3 0000r mov sum,eax
12 0015 B8 4C00 mov ax, 4C00h
13 0018 CD 21 int 21h
14 END start
Groups & Segments Bit Size Align Combine Class

DGROUP Group
STACK 16 0100 Para Stack STACK
_DATA 16 0004 Word Public DATA
_TEXT 16 001A Word Public CODE
Перед кодом команды mov eax,12345678h стоит префикс 66, а перед аналогичной командой mov ax, 4C00h этот префикс отсутствует. Префикс 66 называется префиксом размера операнда. Код команды один и тот же: B8h, но в первом случае операнд 16-разрядный. Вся программа является 16-разрядной. На это указывает разрядность программных секций (колонка Bit). А префикс 66 показывает, что хотя секции 16-разрядные, операнды команды mov eax,12345678h являются 32-разрядными.
Что произойдет, если поставить директиву .386 перед директивой .MODEL small? В листинге мы увидим, что сегменты (программные секции) стали 32-разрядными, а префикс 66 сменил свое место:
9 00000006 B8 12345678 mov eax,12345678h
10 0000000B 05 87654321 add eax,87654321h
11 00000010 A3 00000000r mov sum,eax
12 00000015 66| B8 4C00 mov ax, 4C00h
Можно сделать вывод, что префикс 66h является переключателем. Когда в программе по умолчанию действует 32-разрядный режим, то он указывает, что операнд команды — 16-разрядный, и наоборот.
К сожалению, полученная обменом директив программа неработоспособна. Посмотрим ее код в отладчике:
#add32#9: mov eax,12345678h
cs:0006 B87856 mov ax,5678
cs:0009 3412 xor al,12
Видно, что код команды B8 12345678 интерпретирован неверно.
В дальнейшем мы научимся создавать 32-разрядные приложения для Windows 95 с плоской моделью памяти (.MODEL flat). В этих программах директива .386 будет предшествовать директиве .MODEL, а сейчас запомним, что в программах для MS DOS нужно ставить директиву .386 после директивы .MODEL small!

Для дальнейших упражнений полезно использовать командный файл
3.bat
c: asmin asm /z/zi/la/m %1
IF ERRORLEVEL 1 GOTO exit
c: asmin link /v/3/x %1
pause
c: asmin d %1.exe
:exit
В рассмотренном примере вызов командного файла должен был выглядеть так:
1 add32
(расширение файла не указывать!). Если при трансляции произойдет ошибка, то выполнение командного файла закончиться досрочно, так как операционной системе будет передан код возврата 1 (он попадает в переменную среды ERRORLEVEL).

В следующем примере мы наглядно увидим те преимущества, которые предоставляют новые методы адресации.
Пример. Суммировать содержимое массива двойных слов.
sumdd.asm
JUMPS
.MODEL small
.386
.STACK 100h
.DATA
sum DD 0
v DD 1,2,3,4
LENV = ($ - v)/4
.CODE
start: mov ax,@data
mov ds,ax
mov eax,0 ; В EAX накапливаем сумму
mov ecx,eax
next: cmp ecx, LENV ; Массив исчерпан?
jae done ; Да – на done
add eax,v[ecx*4] ; Прибавить очередной элемент
inc ecx
jmp next
done: mov sum,eax
mov ax,4C00h
int 21h
END start
Прежде чем разбирать эту программу, заметим, что TASM 2.5 транслирует ее без проблем, а TASM 5.0 более строг. Он выдает предупреждение:
Assembling file: sumdd.asm
next: cmp ecx, LENV
*Warning* sumdd.asm(14) Operand size conflict
(Несоответствие размера операндов)
Дело в том, что переменная времени ассемблирования LENV 16-разрядная, а регистр ecx — 32-разрядный. На это предупреждение можно не обращать внимание (код генерируется правильный), но лучше воспользоваться операцией времени ассемблирования LARGE expression — она устанавливает разрядность результата вычисления выражения равную 32:
LENV = LARGE ($ - v)/4
Следующее замечание касается отсутствия привычной команды организации цикла loop next. Эта команда медленнее, чем пара cmp/jne (по этой причине компиляторы языков высокого уровня ее не генерируют).
Осталось разобрать команду add eax,v[ecx*4]. Ее можно было переписать в "каноническом виде" add eax,[ecx*4+v], но в той форме, в которой она приведена в программе, нагляднее смотрится адресация, напоминая выражение из языка высокого уровня — получение элемента массива v с индексом ecx. Благодаря масштабному множителю 4 происходит выборка очередного двойного слова.
Прогоните эту программу в отладчике. В панели данных отобразите элементы массива v как двойные слова (Alt+F10/Display As/Long).
С использованием команд и методов адресации процессора 8086 нам пришлось бы написать эту программу так

mov cx, LENV
mov si, OFFSET v
xor ax,ax
mov dx,ax
n: add ax,[si]
adc dx,[si+2]
add si,4
loop n
mov word ptr sum,ax
mov word ptr sum + 2 ,dx

В этой версии задействовано четыре регистра (ax, dx, cx, si), а в sumdd.asm — только два: eax и ecx. Такая экономия достигнута не только за счет 32-разрядности (eax вместо пары dx:ax), но и за счет того, что ecx играет двойную роль: и как счетчик цикла, и как индексный регистр. Поэтому и в цикле вместо трех команд фактически одна — с учетом того, что цикл можно было переписать так:
mov ecx, LENV - 1
next: add eax,v[ecx*4] ; Прибавить очередной элемент
loop next
Можно сделать вывод, что в 386-м процессоре сделано существенное продвижение к универсальности регистров общего назначения.

Используем текст этой программы, чтобы узнать, как в языке Ассемблера использовать оператор преобразования типа операнда. Допустим, мы хотим помещать в AL младшие байты элементов массива v. Для этого поместим в программу команду:
add al, [ecx*4+v]
Ошибка: Operand types do not match (Несоответствие типов операндов).
Исправление: add byte ptr al, [ecx*4+v] ; Прежняя ошибка: Operand types do not match.
Правильно так: add al, byte ptr [ecx*4+v].

Задача. Дан массив двойных слов (числа беззнаковые). Найти одновременно его максимальный и минимальный элементы в соответствии со следующим алгоритмом. Будем хранить значения максимума и минимума уже просмотренных чисел, а очередные числа будем обрабатывать по два таким образом: сначала сравним два очередные числа, а затем большее из них сравним с максимумом, а меньшее — с минимумом. (При этом на обработку двух элементов мы затратим три сравнения вместо четырех; кроме первой пары, где понадобится всего одно сравнение. Итак, вместо сравнений нам понадобится сравнения. [Кормен, Лейзерсон, Ривест, Алгоритмы: построение и анализ. с. 181]).

17.4. Задание A6.
17.4.1. Формулировка задания
Даны массивы A и B из N двойных слов (Массив B заполнен нулями). Поместить в массив В элементы A, превышающие пороговое значение 40h. Сосчитать количество таких элементов. Поместить в массив C адреса (смещения) этих элементов из массива A. (Числа знаковые).

17.4.2. Решение
COMMENT &
Даны массивы A и B из N двойных слов (Массив B заполнен нулями). Поместить в массив В элементы A, превышающие пороговое значение 40h. Сосчитать количество таких элементов. Поместить в массив C адреса (смещения)этих элементов из массива A. (Числа знаковые).
&
.MODEL small
.386
.STACK 100h
.DATA
A DD 25h, 45h, -37h, 200h
N = LARGE ($ - A) / TYPE A
B DD N DUP(0)
C DW N DUP(0)
count DD 0
.CODE
start: mov ax, @data
mov ds, ax
xor ecx, ecx
mov esi, ecx
next: cmp ecx, N ; Массив A исчерпан?
jae done ; Да - на done
cmp A[ecx * 4], 40h ; Сравнить с пороговым значением
jng t ; Если элемент превышает пороговое значение,
mov eax, A[ecx * 4] ; то скопировать его в массив B
mov B[esi * 4], eax
lea edi, A[ecx * 4] ; а адрес элемента поместить
mov C[esi * 2], di; в массив С
inc esi ; увеличить индекс в массивах B и C
t: inc ecx
jmp next
done: mov count, esi
mov ax,4C00h
int 21h
END start

Оператор времени ассемблирования TYPE имя возвращает значение в зависимости от типа имени: 1 для байтов, 2 для слов и 4 для двойных слов (он аналогичен оператору sizeof языка Си). Если мы изменим тип массива A с DD на DW, то N будет пересчитано автоматически на этапе ассемблирования. Последовательнее было написать не mov eax, A[ecx * 4], а mov eax, A[ecx * TYPE A].
Массив C описан как массив слов, потому что используется 16-разрядная модель памяти.

17.5. Трюки с использованием новых методов адресации
Быстрое умножение на три: lea eax, [eax + eax*2]. Аналогично легко реализовать умножение на 5 и на 9. Разумеется, флаги анализировать бесполезно, команда lea их не изменяет.
Трехоперандное сложение ecx = eax + ebx. lea ecx , [eax + ebx]

17.6. Кодирование команд в процессоре 80386.
Общий формат команды имеет вид:
префиксы команда
Перечислим префиксы, которые могут присутствовать в команде. Каждый из префиксов занимает ровно один байт.
1) блокировка шины LOCK (код F0h) — в многопроцессорных системах запрещает другим процессорам доступ к общей шине;
2) префикс повторения REP/REPZ/REPE (код F3h) или REPNZ/REPNE (код F4h) — используется в строковых командах, которые мы еще не изучали;
3) префикс замены сегмента;
4) префикс-переключатель размера операнда (код 66h);
5) префикс-переключатель размера адреса (код 67h).
Сейчас мы изучаем реальный режим работы процессора, когда размеры операндов и адресов принимаются по умолчанию 16 битам. Поэтому, если в команде используется 32-разрядный операнд или адрес, то перед кодом собственно команды появляются префиксы 66h и/или 67h.
Теперь расмотрим код команды. Под каждым элементом кода укажем, сколько байтов он может занимать.
КОП постбайт SIB disp imm
1/2 0/1 0/1 0/1/2/4 0/1/2/4
Напомним, что disp (displacement) — смещение, imm (immediate) — непосредственный операнд. Формат постбайта нам тоже знаком.
mod reg/КОП r/m

Поле reg теперь кодируется так (в зависимости от используемого режима: 16-битовый или 32-битовый).
поле reg 16 бит 32 бита
000 AX EAX
001 CX ECX
010 DX EDX
011 BX EBX
100 SP ESP
101 BP EBP
110 SI ESI
111 DI EDI

Таблицу для полей mod и r/m приведем только для 32-разрядного режима.
Поле r/m Поле mod
00 01 10 11
w = 0 w = 1
000 EAX EAX+D8 EAX+D32 AL EAX
001 ECX ECX+D8 ECX+D32 CL ECX
010 EDX EDX+D8 EDX+D32 DL EDX
011 EBX EBX+D8 EBX+D32 BL EBX
100 есть SIB есть SIB+D8 есть SIB+D32 AH ESP
101 есть SIB+D32 EBP+D8 EBP+D32 CH EBP
110 ESI ESI+D8 ESI+D32 DH ESI
111 EDI EDI+D8 EDI+D32 BH EDI

Теперь обратимся к новому для нас байту SIB (Scale-Index-Base).

Scale Index Base


Base — это базовый регистр (все регистры общего назначения кроме ESP);
Index — индексный регистр;
Scale — показатель степени двойки, на которую умножается индексный регистр.
Т.к. в двух битах поля Scale можно записать только числа 0, 1, 2, 3, то масштабный множитель для содержимого индексного регистра может быть только таким: 1, 2, 4, 8.
Пример. Проанализируем код команды add eax, v[ecx*4] из ранее рассмотренной программы. В листинге этой команде соответствует строка
66 | 67 | 03 04 8D 00000004r add eax, v[ecx*4]
Коду команды предшествуют префиксы разрядности адреса и операнда. В листинге эти префиксы отделены от кода команды вертикальными чертами. 00000004r — это смещение (displacement) для массива v. Флажок r (relocatable) указывает, что находясь в отладчике, мы можем увидеть в этом поле другое число, т.к. при объединении сегментов это смещение может измениться. 03 — это код операции и бит w.

0 0 0 0 0 0 1 1
КОП add w
Смысл бита w изменился: w = 0 по-прежнему означает, что операнды являются байтами, а w = 1 теперь означает, что операнды — двойные слова.
04 — содержимое постбайта:
0 0 0 0 0 1 0 0
mod = 00 reg = EAX r/m: есть SIB
8D — содержимое байта SIB.
1 0 0 0 1 1 0 1
Scale = 2 Index = ECX Base = 101b


В процессоре 8086 максимальная длина команды составляет 6 байт. В 386-м процессоре длина команды может достигнуть 15 байт. Приведем пример такой команды:
lock mov es:[esi + ecx*8+6],12345678h
Упражнение. Проанализируйте код этой команды в листинге.
Ответ: F0> 66| 26: 67| C7 04 8D 00000004r 12345678

17.7. Новые команды 386-го процессора
Нам предстоит вновь пройти уже изученные группы команд: команды пересылки, арифметические команды и т.д. В этих группах появились новые команды и "обогащены" уже знакомые команды. Одно расширение мы уже видели: теперь команды могут работать с 32-разрядными операндами.

17.7.1. Команды пересылки
Следующая команда копирует содержимое операнда меньшего размера в операнд большего размера. Она работает аналогично команде MOV, но копирует байт в слово, байт в двойное слово, и слово в двойное слово. Возникает вопрос, как при этом заполняются старшие разряды приемника.
пересылка со знаковым и нулевым расширением MOVxX
MOVe with Sign/Zero eXtension
Команда имеет две разновидности:
MOVSX — копирует в старшие разряды знаковый бит;
MOVZX — заполняет старшие разряды нулями.
Пример. Пусть переменная z описана в программе так:
z DB 84h
В регистр AX нужно поместить содержимое байта z с расширением знака. Ранее мы решили бы эту задачу так:
mov al, z
cbw
Теперь мы можем сделать то же самое одной командой:
movsx ax, z
Результат: AX = FF84.

17.7.2. Команды преобразования операндов.
Ранее мы располагали двумя такими командами: cbw и cwd. Первая расширяла со знаком AL в AX, вторая — AX в DX:AX. Добавились команды:
Преобразовать AX в EAX cwde расширяет знак AX в EAX
Conwert Word to Doubleword Extended флаги не изменяются

Преобразовать EAX в EDX:EAX cdq расширяет знак EAX в EDX:EAX
Conwert Doubleword to Quadword флаги не изменяются

Пример:
mov ax, -3 ; ax = FFFD
cwde ; eax = FFFF FFFD
cdq ; edx:eax = FFFF FFFF: FFFF FFFD

17.7.3. Команды умножения
В процессоре 8086 — две команды умножения: mul и imul. Команда mul теперь может работать и с 32-разрядными операндами.
для байтов: для слов: для двойных слов:
AL AX EAX
 
src src src


AH AL DX AX EDX EAX
То же самое верно для команды imul. Но команда imul ранее имела только один формат (imul src), а теперь три.
1) imul src
2) imul reg, src reg reg * src
3) imul dst,src,imm dst src * imm
Поясним новые обозначения: reg (register) — регистр, imm (immediate) — непосредственный операнд. (Далее будем писать еще короче: вместо reg — r, а вместо imm — i, указывая при этом размер в битах.) Первый из форматов мы уже изучили. Во втором и третьем форматах придется точно описать возможные размеры операндов
2) imul r16, r/m16 imul r32, r/m32 imul r16, i8/i16 imul r32, i8/i32
3) imul r16, r/m16, i8/i16 imul r32, r/m32, i8/i32
Непосредственный операнд при необходимости расширяется со знаком. Размер результата равен наибольшему из размеров операндов, поэтому при умножении возможно переполнение (это исключено в первом варианте команды imul). Переполнение фиксируется установкой флагов CF = OF = 1.
Пример. y DW 19

imul cx, y, 7; cx y * 7
Почему аналогичных новых вариантов не появилось для команды mul? Они не нужны! Ведь второй и третий варианты команды imul работают в кольце Zk, где k=216 или k=232. В этом кольце знаковые и беззнаковые числа неразличимы. Поэтому можно использовать IMUL и для беззнаковых операндов. Ведь младшая половина результата одна и та же и для знаковых и для беззнаковых операндов. Но полной эквивалентности mul и imul все-таки нет, так как для MUL флаги CF и OF не просигнализируют о переполнении.
Пример. mov ebx, 0FFFFFFFFFh
imul ecx, ebx, 3
В результате ECX = 0FFFFFFFDh = –3, CF = OF = 0.
Для беззнаковых операндов этот результат неверен, в чем можно убедиться, используя команду mul:
mov eax, 0FFFFFFFFFh
mov ebx, 3
mul ebx ; 2 FFFFFFFDh

17.7.4. Деление
Для команд деления добавляется возможность работы с 32-разрядными операндами.

делимое делитель EDX:EAX src
остаток частное EDX EAX

Пример. Перепишем программу для задания A2. Напомним его:
Пусть x, z — байты, y, v — слова. Вычислить

Будем размещать операнды в 32-разрядных регистрах.

x DB 1
y DW –3
z DB 4
v DW 0
.CODE
start:mov ax, @data
mov ds,ax
movsx eax,z
dec eax
movsx ebx,y
imul eax, ebx
inc eax
cdq
movsx ecx, x
add ecx, 3
idiv ecx
inc ax
mov v, ax

Упражнение. Перепишите свое задание A2 с использованием новых команд.

17.7.5. Команды условного перехода.
Ранее диапазон, в котором мог совершаться условный переход был следующим [–128; 127]. Теперь он расширился: [–32768; 32767]. Смещение может храниться не только в байте, но и в слове. Посмотрим, какие при этом возникают особенности. Рассмотрим программу, для которой здесь приведен лишь фрагмент. Подготовьте полную программу и проверьте все нижеследующие утверждения.
1) Первый вариант программы предназначен для процессора 8086.
.MODEL small
.STACK 100h
.CODE

cmp ax,bx
jne t
REPT 200h
nop
ENDM
t: inc ax

При трансляции такой программы будет сообщение об ошибке:
Relative jump out of range by 0181h bytes
2) Добавим директиву .386. Сообщение об ошибке исчезнет, а в листинге мы увидим код команды:
0F 85 0200 jne t
Код операции теперь составляет два байта и смещение записано в слове.
3) Заменим теперь REPT 200h на REPT 20h. Тогда в листинге мы увидим:
75 22 90 90 jne t
Добавились две команды nop, чтобы заполнить адресное пространство кода, предназначенное для другого формата команды перехода.
4) Чтобы избавиться от паразитных команд, включим директиву JUMPS и проведем многопроходную трансляцию (tasm/m). Будет сгенерирована команда
75 22 jne tt

Команда jcxz по-прежнему работает только в диапазоне [–128; 127]. Добавилась команда jecxz, которая осуществляет переход, если регистр ecx содержит 0.

17.7. Стек.
Ранее в стеке хранились слова. Теперь в стеке двойные слова. Соответственно изменились команды push и pop. Теперь содержимое ESP уменьшается (увеличивается) на 4, чтобы произошел переход к соседнему двойному слову.
По-прежнему EBP может использоваться для адресации стекового кадра. Однако появилась возможность использовать ESP в качестве базового регистра в косвенной адресации. (Мы подробно рассмотрим это при изучении механизма передачи параметров подпрограммы в языке Си в среде Visual C++.)