Реальный набор инструкций, но он не имеет значения, и не заинтересован в том, как эта реальная инструкция работает, он будет служить для демонстрации проблемы.
2000: 0b 12 push r11
2002: 3b 40 21 00 mov #33, r11
2006: 3b 41 pop r11
2008: 30 41 ret
Как уже упоминалось, когда речь идет о счетчике программ, существует понятие времени.
Можно подумать о таком сверхпростом процессоре, старом 8-битном и других, новые же отличаются.
Когда мы вводим этот код, как бы мы здесь ни находились, это не имеет значения. Счетчик программ
0x2000 Это говорит нам, где выбрать инструкцию, которую мы должны получить, декодировать, а затем выполнить, повторить.
Это 16-битные инструкции, два байта, процессор начинает извлекать, когда компьютер указывает на инструкцию, то есть адрес инструкции. Процессор считывает два байта один по адресу 0x2000 (0x0b), процессор увеличивает счетчик программы до 0x2001 и использует его для извлечения второй половины инструкции по адресу 0x2001 (0x12) и увеличивает счетчик программы до 0x2002. Таким образом, для каждой выборки в этом, давайте назовем это составленным процессором, который я описываю для каждой выборки, которую вы выбираете, используя счетчик программ в качестве адреса, затем увеличивайте счетчик программ.
before data after
0x2000 0x0b 0x2001
0x2001 0x12 0x2002
Итак, теперь мы декодируем инструкцию, счетчик программы в настоящее время показывает 0x2002, мы видим, что это push r11, поэтому мы переходим к выполнению.
Во время выполнения этой инструкции счетчик программы остается равным 0x2002. Значение регистра r11 помещается в стек.
Теперь мы начинаем получать следующую инструкцию.
before data after
0x2002 0x3b 0x2003
0x2003 0x40 0x2004
Когда мы декодируем эту инструкцию (pc == 0x2004) mov # немедленное, r11 процессор понимает, что для этой инструкции требуется немедленное выполнение, поэтому ему нужно получить еще два байта
before data after
0x2004 0x21 0x2005
0x2005 0x00 0x2006
Он определил, что теперь может выполнять инструкцию (младший порядок 0x0021 = 33 десятичного), записав значение 0x0021 в регистр r11. Во время выполнения счетчик программы для этой инструкции равен 0x2006.
следующий
before data after
0x2006 0x3b 0x2007
0x2007 0x41 0x2008
декодировать и выполнить поп-код r11
Таким образом, вы можете начать видеть, что программный счетчик действительно содержит как минимум два значения. В начале инструкции перед извлечением она содержит адрес инструкции, после извлечения и декодирования непосредственно перед тем, как мы начнем выполнять, она содержит адрес байта после этой инструкции, который, если это не переход, является другой инструкцией. Если это безусловный прыжок, то
байт может быть инструкция или некоторые данные, или неиспользованная память. Но мы говорим, что
в этом случае он «указывает на следующую инструкцию», то есть перед выполнением
адрес после этой инструкции, которая часто имеет другую инструкцию. Но, как мы увидим дальше, компьютер может быть изменен инструкцией. Но всегда в конце
выполнения это указывает (для этого простого составленного процессора, который похож на
количество простых 8-битных процессоров) до следующей выполняемой инструкции.
наконец
before data after
0x2008 0x30 0x2009
0x2009 0x41 0x200A
декодирует ret, теперь этот является особенным для вопроса, потому что ret собирается изменить счетчик программы во время выполнения согласно правилам этого процессора. Если команда, которая назвала адрес 0x2000, была, скажем, 0x1000, и это была двухбайтовая инструкция, то после выборки и во время декодирования счетчик программы будет находиться по адресу 0x1002, во время выполнения адрес 0x1002 будет храниться где-то в соответствии с правилами этого набора команд и Программный счетчик примет значение 0x2000 для вызова этой подпрограммы. Когда мы добираемся до инструкции ret и начинаем ее выполнять, мы начинаем выполнение ret со счетчика программы, содержащего 0x200A, но ret помещает адрес инструкции после вызова, значение сохраняется во время выполнения вызова, поэтому при В конце этой инструкции счетчик программы будет содержать значение 0x1002, и следующая выборка будет с этого адреса.
Так что в этой последней инструкции перед выполнением ПК указывает на то, чтокак правило, следующая инструкция для инструкций, которые не ветвятся или прыгают
вызов. 0x200A. Но во время выполнения счетчик программы был изменен так, чтобы
«следующая» инструкция - та, что после вызова, которая привела нас сюда.
еще немного
c064: 0a 24 jz $+22 ;abs 0xc07a
c066: 4e 5e rla.b r14
перед загрузкой компьютера 0xC064. после выборки и декодирования ПК равен 0xC066. Инструкция гласит: переходите к 0xc07a. Таким образом, если нулевой флаг не установлен, компьютер остается на 0xC066, и именно здесь он начинает следующую инструкцию, но если z
установить затем ПК изменяется на 0xc07a, и именно там следующая инструкция
выполнить будет. Так что до 0xc064 после 0xc066 или 0xc07a в зависимости.
После одной инструкции - до следующей.
безусловный прыжок
c074: c2 4d 21 00 mov.b r13, &0x0021
c078: ee 3f jmp $-34 ;abs 0xc056
до получения 0xc07a, до выполнения 0xc07A после выполнения 0xc056
для этой одной инструкции ПК содержал как минимум три значения (при извлечении байта
в то время он удерживал 0xc078, 0xc079, 0xc07a и заканчивался 0xc056) в течение
одна инструкция.
да, он может содержать и удерживает более одного значения, но не одновременно, по одному значению за раз на этапах инструкции.