Скопировать байт из стека без изменения указателя стека (Motorolla 68000)?

Мне задают следующий вопрос:

Three  bytes  are  pushed  onto  the  runtime  stack.  Copy  the  third  
byte  from  the  runtime  stack  to D0 without changing the stack pointer

Итак, у меня есть стек, который выглядит так:

|   |
|   |
|cc | <-- SP points to cc
|bb |
|aa |

Я не уверен, как мне скопировать значение cc в регистр D0. Я знаю, что могу вытащить его из стека вот так... MOVE.B (SP)+,D0, но это изменит указатель стека так, чтобы он указывал на bb

Также в чем разница между пользовательским стеком и стеком времени выполнения? Например, если меня попросят извлечь байт из пользовательского стека (A6), а затем поместить его в стек времени выполнения, как мне это сделать? Любые идеи?


person TTEd    schedule 01.12.2015    source источник
comment
Не уверен в синтаксисе, но это что-то вроде MOVE.B 3(SP),D0,   -  person user207421    schedule 01.12.2015
comment
3 впереди - это предварительное приращение 3, но указатель стека уже указывает на то, что я хочу скопировать? Так разве это не копирование значения на 3 пробела выше cc, что ничего не значит? Ваш синтаксис в порядке, но я' м не уверен насчет значения '3'   -  person TTEd    schedule 01.12.2015
comment
Тогда это просто (SP), не так ли? NB "3(SP)" не является "предварительным приращением 3", это индексированный непрямой доступ, 3 плюс значение SP.   -  person user207421    schedule 01.12.2015


Ответы (2)


Вам нужно использовать смещение указателя стека. Также помните, что стеки идут в обратном направлении (обычно :)), поэтому

move.b (sp), d0

даст $cc в вашем примере

move.b 2(sp), d0

принесет вам $aa в d0

надеюсь, это поможет

person Graeme    schedule 01.12.2015
comment
Обычная фраза - стеки растут вниз. Говоря задом наперёд, кажется, что справиться с этим сложнее, чем на самом деле :P. - person Peter Cordes; 01.12.2015
comment
Просто я всегда это слышал :) любая фраза, вероятно, будет работать по-разному для разных людей. Для меня вниз означало бы положительное приращение адреса. тогда как вперед и назад переводятся просто в положительные и отрицательные приращения (по крайней мере, для меня). - person Graeme; 01.12.2015
comment
Хм, если смещение 2 дает aa (нижняя часть стека), будет ли смещение 1 давать bb? - person TTEd; 01.12.2015
comment
Да. 0(sp) равнозначно (sp), 1(sp) похоже на sp + 1 и так далее. Однако будьте осторожны, чтобы не пытаться прочитать слово или длинное слово со странного адреса :) - person Graeme; 01.12.2015
comment
@Graeme: очень часто диаграммы расположения памяти показываются со старшими адресами вверху и младшими адресами внизу. например nickdesaulniers.github.io/images/stack.png. (из nickdesaulniers.github.io/blog /2014/04/18/, найдено с помощью поиска изображений Google для стека, растущего вниз). Обратное звучит для меня так, как будто вы говорите о сравнении с обычными массивами/буферами, поэтому вы получаете стек, растущий вниз, помня, что он отстает от нормального, поэтому вам нужно подумать о дополнительном шаге. Без понятия, как вы спускаетесь = положительный прирост. - person Peter Cordes; 01.12.2015
comment
Я не спорю, что это общий термин, просто другой. Точно так же, если вы сделаете тот же поиск в Google для стека, который растет в обратном направлении, вы также найдете много результатов. - person Graeme; 01.12.2015
comment
Я думаю, вы привыкли к диаграммам с младшими адресами слева, а назад означает справа налево? Мой мозг болит от попытки думать таким образом в течение 2 секунд. Хех, достаточно честно, я проверю это в следующий раз, когда захочу навредить своему мозгу. :P В любом случае, да, я не пытался сказать, что ты был неправ, просто кажется очень странным думать об этом. Я не понимал, что это вообще обычное дело. - person Peter Cordes; 01.12.2015
comment
Я привык смотреть на память в дизассемблерах или в дампе вывода, в этих случаях адрес памяти $00 будет вверху, а $ff внизу. Кроме того, когда вы пишете код, первая строка кода ассемблируется (для аргумента :) ) в $00, следующая — в $02 и так далее. Я предполагаю, что это связано с чтением слева направо, сверху вниз. Для меня нет лишнего мысленного шага назад, но есть шаг вниз. Как я уже говорил ранее, это, вероятно, зависит от человека и / или от того, как его учили / учили. - person Graeme; 01.12.2015
comment
@Грэм: понятно. Это имеет смысл. Я согласен с вашим выводом, что другой путь звучит странно, к какому бы вы ни привыкли. :P В дампе памяти стека я бы просто автоматически начал читать с последней строки, как и вы, так как я знаю, что это стек. Так что на практике это работает так же. - person Peter Cordes; 01.12.2015

Это вопрос с подвохом, и на него нельзя ответить, не зная, каким образом байты попали в стек, особенно потому, что существует странность при использовании адресного регистра с режимом предварительного декремента -(An), когда An=A7=SP. Если, например, байты были помещены так:

move.b #$aa,-(sp)
move.b #$bb,-(sp)
move.b #$cc,-(sp)

|$??| +5
|$aa| +4
|$??| +3
|$bb| +2
|$??| +1
|$cc| <--- SP points here

Указатель стека уменьшается на два при каждом перемещении. 68k обрабатывает это иначе, чем другие адресные регистры, потому что нечетный адрес указателя стека вызовет исключение адреса (по крайней мере, для MC68000) при следующей попытке поместить слово или длинное слово (явно или неявно с помощью вызова подпрограммы) из-за слово/длинный доступ по нечетному адресу. Это описано в справочном руководстве по семейству, стр. 2-7: http://www.freescale.com/files/archives/doc/ref_manual/M68000PRM.pdf

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

move.l #$ccbbaa??,-(sp)

|$??| +3
|$aa| +2
|$bb| +1
|$cc| <--- SP points here

Таким образом, ответ будет примерно таким: «move.b 4(sp),d0», если они были переданы как байты, и «move.b 2(sp),d0», если они были частью большего объекта.

person Durandal    schedule 05.12.2015