Как регистры памяти используются для хранения разных типов? - PullRequest
2 голосов
/ 15 февраля 2012

У меня сложилось впечатление, что если программа резервирует память для типа переменной integer (что составляет 8 байт), то зарезервированная память будет состоять из 8 различных регистров, которые последовательно появляются в памяти.

Мои вопросы следующие:

1) Если предположить, что ответы будут разными, мое утверждение, приведенное выше, является хорошим обобщением того, что каждый байт, требуемый различными типами переменных, приравнивается к этой переменной с использованием 1 регистра в памяти? (то есть 1 байт требует один регистр в памяти)

2) Если это правда, сколько бит каждый регистр хранит в памяти? Или если я купил 32-битный компьютер, значит ли это, что каждый регистр в памяти содержит 32 бита?

3) А если целочисленному типу нужны 8 разных регистров размером 8 байтов, что содержится в каждом другом регистре?

4) Также я пытаюсь понять идею типов. Я знаю, что если у вас есть 32 бита для работы, вы могли бы представлять целое число без знака значения от 0 до 4294967295. Тем не менее, если бы я хранил целое число без знака 4294967295 в ячейке памяти из 32 бит как процессор узнает, что двоичное представление в этой ячейке памяти должно быть декодировано в формат unsigned integer ? То есть, память, выделенная для определенного типа, определяет этот определенный тип, или указатель указывает тип, или, возможно, что-то совершенно другое?

Я, как правило, хорошо знаком с идеями двоичной арифметики, языка ассемблера, ссылок, указателей и того, как переменные и массивы хранятся в куче памяти (поэтому я пойму любые ответы с использованием этих контекстов). И я могу программировать на C, C ++ и Java. Спасибо за любую помощь.

Ответы [ 2 ]

2 голосов
/ 15 февраля 2012

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

Дейкстра: «Информатика не больше о компьютерах, чем астрономияо телескопах ».

Вам необходимо указать процессор, который вас интересует, или вы заинтересованы в процессорах в целом.На сегодняшний день общее сочетание процессоров варьируется от 8-разрядных регистров до 64-разрядных и более с процессорами на основе 8-разрядных, 16-разрядных, 32-разрядных и 64-разрядных регистров.

Также не путайтесь во всемНаходясь в регистре, некоторые процессоры имеют много регистров, и многие элементы в вашем коде высокого уровня некоторое время сидят в регистрах, в то время как другие процессоры не имеют много регистров, и большинство ваших переменных живут в ОЗУ, а не в регистрах.Чаще всего переменные будут иметь некоторую оперативную память, даже если регистр хранит эти данные в течение длительных периодов времени.Оптимизаторы действительно портят этот баланс, хотя сделать общие утверждения сложно.

Вы говорите, что знаете язык ассемблера, возьмите псевдокод этого языка ассемблера, например:

mov r1,#0x20000000
shl r2,r0,5
add r1,r2
ldr r0,[r1]

Это похоже на то, что выможет увидеть, если у вас есть массив структур размером 32 байта, и вы хотите получить в первом элементе, скажем, это был float с одинарной точностью.И вы хотели, чтобы число с плавающей запятой от номера элемента в массиве, хранящемся в регистре r0, нас не волнует, что это за номер элемента, код работает на том, что он есть.

struct 
{
  float f;
  stuff...32 bits total
} mystruct[MYSTRUCTSIZE];
...
unsigned int i;
...
something=mystruct[i].f
...

Приведенный выше псевдокод сборки вычисляетmystruct [i] .f адрес и загружает его из памяти, чтобы вставить или использовать что-то в коде.

Биты 0x20000000, которые мы можем знать, это некоторый адрес в памяти, где живет этот массив структур, нона данный момент для команды mov это всего лишь биты, непосредственное значение, которое мы загружаем в регистр.Часто инструкция mov не влияет на флаги, поэтому она не имеет никакого знака или без знака или какого-либо значения для процессора, за исключением некоторых битов, поступающих в регистр.Предположим, что 32-битные регистры и адресное пространство для этого псевдокода

Как уже упоминалось, r0 хранит индекс в массиве структур, поэтому мы умножаем на 32, инструкция сдвига влево не заботится о том, что это индекс или что сдвиг5 имеет отношение к структурам, это просто биты, подаваемые в alu, заставляющие биты сдвигаться с одной стороны и нули смещаться с другой.Некоторые процессоры будут переносить последний бит, сдвинутый в бит переноса, не как бит переноса, а как заполнитель для каскадных сдвигов, аналогично можно вычислить zflag и флаг n (знаковый бит) на тот случай, если вы считаете, что эточисло дополнения до двух (после сдвига), или хотите несколько ярлыков в программировании.Но это всего лишь биты для процессора, не имеет никакого значения.

В этот момент мы, люди, думаем о том, что r2 удерживает смещение в памяти для индекса в массиве структур, но для процессора - его просто биты.Мы выполняем доп.мы считаем один операнд адресом, а другой - смещением, но для процессора это всего лишь биты, которые обрабатываются.Обычно Add не заботится о подписи и без знака, прелесть дополнения к двум заключается в том, что вы можете подавать неподписанные и подписанные в одну и ту же логику сумматора, которая часто вычисляет флаг выполнения (переполнение без знака) и флаг v (переполнение со знаком) плюс флаг z, ноль и n помечают отрицательный результат, все в одном кадре, ни один, если он не имеет никакого значения для добавления, просто вычисляется как результат в случае, если вы хотите использовать флаги для чего-то.В этом случае процессор не может знать, что мы вычисляем адрес.

А теперь мы определяем биты в регистре как адрес и выполняем загрузку. Но процессор рассматривает только как адрес для этой одной инструкции, тот момент времени, который регистрируется за несколько мгновений до того, как некоторые биты были результатом операции добавления.

Что мы читаем по памяти? больше битов, а не значение с плавающей запятой, просто 32 бита. Теперь у некоторых процессоров может быть прямой способ загрузки из памяти непосредственно в регистр с плавающей запятой, у некоторых процессоров нет плавающей запятой, и все это синтезируется с помощью регистров общего назначения. Даже те с плавающей точкой могут использовать gprs для значений с плавающей точкой, если, например, код выше делал это:

mystruct[j].f=mystruct[i].f;

Вы, возможно, не захотите записывать регистр fpu, если можете, вы можете использовать gpr, как я указал ниже. Если рядом с этим кодом не было действительной математики с плавающей запятой, это просто биты, перемещаемые из одного места в другое, без причины вовлекать процессор.

Приведенная выше строка кода может выглядеть так, когда все сказано и сделано:

ldr r1,mystruct_base
shl r2,r0,#5
add r2,r2,r1
ldr r0,[r2]
shl r2,r3,#5
add r2,r2,r1
str r0,[r2]

где r0 - это i, когда этот код введен, а r3 - j. Процессор не знает и не заботится о том, что это за биты, за некоторыми исключениями. для ldr и str r2 для периода времени инструкции считается адрес в памяти к чему-либо. кроме этого нет структур или чисел с плавающей запятой или целых чисел со знаком или без знака. Ничего такого. Просто биты.

Да, обычно, когда кто-то говорит 32-битный компьютер, он имеет в виду 32-битные регистры. Это хорошее обобщение, часто размер битов и размер адреса шины памяти, 32 бита, означающие, что теоретически вы можете адресовать 32-битную память, 4 ГБ. Это становится немного неясным, хотя, как вы знаете из x86 или других. Часто, особенно с x86, вы увидите 64-битный процессор, работающий в 32-битном режиме, в основном выполняющий код / ​​инструкции, которые ожидают, что 32-битные регистры не 64-битные, с x86 «регистры» имеют разные способы доступа к ним как 8, 16, 32 или 63 бита, так что вы можете играть в эти игры.

На все эти и другие вопросы вы получите ответы на языке ассемблера для процессора. Теперь, к сожалению, mips пытается сбить вас с толку, и x86 тоже делает это, так что избегайте этого, сначала выберите что-нибудь простое, например msp430, ARM или ARM в режиме большого пальца.

2 голосов
/ 15 февраля 2012

1, 2, 3: не относиться к памяти как к регистрам;хотя я видел, что сделано, прежде чем это сбивает с толку.64-разрядный процессор имеет 8-байтовые регистры, а 32-разрядный процессор имеет 4-байтовые регистры, но когда эти регистры копируются в ОЗУ, это просто байты в памяти.Какая часть целого числа хранится, в каком байте зависит от порядкового номера процессора: система с прямым порядком байтов будет хранить 1 бит в 0x1 по первому (младшему) адресу из 8 байтов, а система с прямым порядком байтов будет хранитьэто в последнем.

4: процессор не знает и не заботится;«types» - это языковая конструкция высокого уровня, для процессора все является числом: «abcd» - это число, а 0xf0f0f0f0 - это число.вы должны дать ему инструкции в соответствии с тем, что вы хотите, например, для x86 используйте IDIV вместо DIV, если вы хотите, чтобы число трактовалось как подписанное.

...