CS221. Архитектура компьютера и операционные системы

Вопрос по 3 заданию из 5 лабы. “Внутри AddRightDigit косвенное обращение по адресу [локальной] переменной должно происходить при помощи регистра BP, так как переменная изначально выделена в сегменте стека.” Если у AddRightDigit 2 аргумента: цифра(сдвиг 6) и адрес числа(сдвиг 4), к которому мы должны приписать эту цифру, и в другой подпрограмме я кладу на стек сначала эту цифру, а потом локальную переменную -2(BP), когда я в AddRightDigit обращаюсь к 4(BP) это правильно?

Локальную переменную положить никуда нельзя, нужно положить её адрес. То есть число, равное BP - 2. Это можно сделать так, например:

MOV  AX, BP
SUB  AX, 2
PUSH AX

Можно чуть быстрее:

LEA  AX, -2(BP)
PUSH AX

Эффект будет тот же. Про LEA можно погуглить.

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

то есть если написать

PUSH   -2(BP)

то на стек положится значение этой переменной?

Конечно.

обязательно BP? BX/SI/DI нельзя?

Ну, вы можете проверить, по крайней мере. Тут два соображения.

  1. Если вы вспомните о том, что говорилось на прошлой лекции, то поймёте, что адрес (BP) = (SS:BP), и он в общем случае не равен (BX) = (DS:BX), даже если положить в BP и BX одинаковые значения.

  2. Мы работаем на очень упрощённом симуляторе. Как он там учитывает сегментную часть, я точно не знаю: надо или экспериментировать (чего я не делал) или найти в тексте приложения про этот ассемблер в книге. Если вы разберётесь, что да как (например: симулятор вообще не учитывает сегмент или симулятор всегда делает сегментные части равными 0x0000, потому разницы нет) и напишите здесь, то будет здорово.

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

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

Если я правильно поняла конечно. Так и написать?

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

Хорошо. А можно в AddRightDigits AX и CX сохранить на стеке, чтобы их не испортить?

По cdecl эти регистры сохраняются вызывающей подпрограммой, а не вызываемой.

будет что-то вроде

PUSH   BP
MOV    BP,  4(BP)
...
POP   BP

eсли в 4(BP) адрес переменной, да?

Да, именно так.

Cпасибо, вроде разобралась

737 стр. Таненбаума:

На самом деле, сегмент данных и стековый сегмент относятся к одной и той же области памяти, но данные хранятся на дне этого общего сегмента, а стек — на вершине.

оно?

Да, точно, спасибо. Это так называемая модель TINY, они используют её по умолчанию и не дают других возможностей. В реальности бывает по-разному.

Поэтому работает только с BP?

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

Артем Михайлович, я забыл указать в своих файлах с кр номер варианта и фамилию=( Если это как-то поможет делу - Галайчук Виталий, второй вариант.

Хорошо, принято. Но оценка будет снижена. Я многократно обращал внимание на необходимость следовать требованиям оформления.

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