Что именно делает инструкция lb?

Вопрос или проблема

Что именно делает инструкция lb?

У меня скоро экзамен, и одна из практических задач звучала так:

Предположим, что $t0 содержит значение 0x12121212, а $t1 содержит
адрес 0x1000000.

Предположим, что данные в памяти, начиная с адреса 0x1000000, составляют:
88 77 66 55.

Каково будет значение $t0 после выполнения следующего кода:

lb $t0, 0($t1)

a) 0x00000088 b) 0x88121212 c) 0xffffff88 d) 0x12121288

Ответ, который я дал, был a, потому что байт, который команда lb прочитает (по моему пониманию того, что делает эта команда), равен 88. Значение 88 затем будет сохранено в $t0, и таким образом значение станет 0x00000088. Но ответ был указан как c. Мне кажется, у меня есть фундаментальное недопонимание того, как работает lb – может кто-то объяснить, почему ответ c?

Ответ будет c) 0xffffff88. Команда lb делает знаковое расширение байта до 32-битного значения. То есть старший бит (msb) копируется в верхние 24 бита.

0x88 == 0b10001000, т.е. старший бит равен 1. Поэтому верхние 24 бита будут 0b111111111111111111111111 == 0xffffff.

Команда lb загружает байт из памяти и делает знаковое расширение до размера регистра. Команда lbu делает то же самое без знакового расширения (без знака).

http://en.wikipedia.org/wiki/MIPS_architecture#Integer

Большинство компьютеров, включая MIPS, используют двоичное представление со знаком для представления знаковых значений, хотя существуют другие способы кодирования знака, числа с плавающей точкой обычно представляются в формате IEEE 754, который использует представление со знаком. Знаковое целое число может быть представлено в любом количестве бит, например:

  • char в C занимает 8 бит и может представлять значения от -128 до +127
  • short в C занимает 16 бит и может представлять значения от -32768 до +32767
  • и т.д.

В двоичном представлении со знаком самый старший бит может использоваться для определения знака числа, '1' означает, что число отрицательное, а '0' означает, что число положительное.

Число 0x88, когда интерпретируется как 8-битное двоичное число со знаком, является отрицательным равным 0x78 или -120 в десятичной системе. При представлении в 32 бита в двоичном представлении со знаком это будет 0xFFFFFF88. Существуют несколько способов запомнить, как вычислить двоичное дополнение числа:

  • взять дополнительный код числа (инвертировать каждый бит) и прибавить ‘1’, или
  • идти от младшего бита к старшему (справа налево), пропустив каждый ‘0’ и первый ‘1’, который вы встретите, инвертировать каждый бит после этого

Чтобы сделать знаковое расширение с 8 бит до 32 бит, просто посмотрите на самый старший бит (бит 7) и скопируйте этот бит в биты с 8 до 31… Это вытекает из определения двоичного дополнения.

Ответ или решение

Инструкция lb (load byte) в архитектуре MIPS загружает один байт памяти и расширяет его до 32 бит с учетом знака. Давайте разберемся, как это работает на конкретном примере.

Условия задачи

Предположим, что:

  • Регистр $t0 изначально содержит значение 0x12121212.
  • Регистр $t1 содержит адрес 0x1000000.
  • В памяти, начиная с адреса 0x1000000, расположены данные: 88 77 66 55.

Что делает инструкция lb $t0, 0($t1)?

  1. Чтение байта из памяти:
    Инструкция lb обращается по адресу, указанному в регистре $t1 (в данном случае, 0x1000000), и считывает один байт. Первым байтом по этому адресу является 0x88.

  2. Расширение знака:
    После того как мы прочитали байт 0x88, этот байт интерпретируется как 8-битное знаковое число. В двоичном представлении 0x88 — это 10001000. В этом представлении старший бит (бит 7) равен 1, что указывает на то, что число отрицательное в системе представления со знаком (двойное дополнение).

    В двоичном виде:

    • 0x88 = 10001000 (в 8 битах)
    • Как знаковое число, оно эквивалентно -120 в десятичной системе.
  3. Расчет 32-битного представления:
    Чтобы представить 0x88 как 32-битное число с учетом знака, необходимо заполнить старшие 24 бита значением старшего бита (бит 7). Так как старший бит равен 1, мы заполняем старшие 24 бита единицами:
    • Результат: 0xFFFFFF88.

Ответ

Таким образом, после выполнения инструкции lb $t0, 0($t1), значение в регистре $t0 станет 0xFFFFFF88.

Следовательно, правильный ответ на вопрос, что будет содержать регистр $t0 после выполнения этой инструкции, — это вариант c:

  • c) 0xffffff88.

Эта информация должна помочь вам лучше понять работу инструкции lb и расширение знака в MIPS. Удачи на экзамене!

Оцените материал
Добавить комментарий

Капча загружается...