# #assembly #x86
Вопрос:
Я изучаю язык ассемблера, и мы следуем архитектуре IA-32. У меня есть небольшая путаница между терминами «ширина регистра» и размером памяти. На первой лекции нас учили, что во время нашего курса обучения мы будем считать, что «ширина регистра составляет 32 бита(4 байта)». Затем, в следующей лекции мы изучаем типы данных, и в качестве примера нам сказали, что если необходимо сохранить целое число 5(4 байта), то каждый байт будет отправляться в одно адресное пространство памяти, поэтому по этой логике хранение int 5 будет охватывать четыре адреса памяти (так сказать, 0-3). Прав ли я в своем мышлении? Или я где-то неправильно понял концепцию? Поправьте меня, потому что проведение различия между терминами «ширина регистра» и «адрес памяти» некоторое время сбивало меня с толку. Спасибо!!
Комментарии:
1. Вы правы, если 32-битный регистр, например,
EAX
хранит целое число со значением 5 , его четыре байта будут сохранены в памяти до четырех байтов. Когда вы зарезервировали память и присвоили ей метку, напримерMyMem DD 0
, число 5 будет сохранено инструкциейMOV [MyMem], EAX
в байтах, адресованных какMyMem 0
,MyMem 1
,MyMem 2
,MyMem 3
. Последние три байта в памяти будут равны нулю, потому что IA-32-это маленький конечный код.
Ответ №1:
Память большинства процессоров «адресуема к байтам», то есть адрес, о котором мы говорим и который мы используем в качестве указателей и т. Д., Определяет конкретный байт в памяти (не собираюсь переходить в виртуальную или физическую, просто сверните с ним). Это никоим образом не означает, что память создается и адресуется в байтах. Часто, конечно, в 32-разрядном процессоре x86 шины, которые могут нести память, будут иметь минимум 32 бита, но, вероятно, больше. Sram, используемые для кэширования, безусловно, не будут адресованы в байтах с точки зрения sram.
Как это работает, если вы решите выполнить доступ к байтам, так это то, что для чтения, скажем, все имеет ширину 32 бита (шины, кэш-память, интерфейс dram и т. Д.), И вы хотите прочитать какой-то адрес, скажем, 0x1001, что произойдет, если 32 бита начинаются с адреса 0x1000 (с точки зрения адресации байтов 0x1000, 0x1001, 0x1002 и 0x1003), И следующий за наименее значимым байт (0x0000XX00) будет извлечен обычно в процессоре, а не в конце памяти.
Для записи шина в этом примере составляет 32 бита, поэтому вам в значительной степени придется что-то туда поместить (или позволить этому быть высоким, но я в этом сомневаюсь), поэтому на шине будет выходить некоторый мусор, возможно, предсказуемый, если вы знаете процессор (устаревшие данные из какой-то защелки где-то в интерфейсе шины), поэтому я хочу написать 0x1001, поэтому, основываясь на правилах шины, на шине будет по крайней мере один байт, который должен быть записан, и некоторые управляющие сигналы на шине, указывающие, что это однобайтовая запись и какой байт и адрес.
Затем, когда вы нажимаете на эти 32-разрядные (для данного примера) модули SRAM и DRAM, происходит чтение-изменение-запись (в кэше, как можно было бы надеяться), поэтому считывается полное 32 — разрядное значение, изменяется один байт и 32-разрядное значение записывается обратно (в идеале в SRAM в кэше). Затем, в идеале, когда кэш очищает строку кэша, содержащую этот байт, эти записи происходят в кратных значениях выбранной нами ширины, 32 бита.
Предполагая, что вы это поняли, реальность такова, что вы можете купить несколько шин, несколько кэшей и множество модулей dram, а также несколько поколений 32-разрядных процессоров x86 (и если вы добавите все остальные arm, mips и т. Д., Просто умножит различные реализации). Нет причин предполагать, что любые две шины в одной и той же системе имеют одинаковую ширину, довольно веская причина предполагать, что они имеют ширину не менее 32 бит, но, вероятно, кратную 32 или 64. Каждая из SRAM будет кратна 32 битам, вероятно, если не 64. Таким образом, для каждого доступа, меньшего ширины этой sram, должно происходить чтение-изменение-запись. Даже если, скажем, у вас 32-разрядный процессор x86, но шина 64 бита, sram 64 бита, 32-разрядная передача, 16 бит, а также 8 генерирует где-то чтение-изменение-запись.
DRAM если вы посмотрите на модули, которые вы можете купить, вы можете увидеть некоторые из них с 9 частями с одной или с каждой стороны. Или 4 части, или 5 частей и т. Д. С течением времени для технологии вы часто видите детали dram шириной 8 бит, и вы бы опустили 8 или 9 в зависимости от того, есть ли поддержка ECC или нет (или 16 или 18, если это двойной ранг, детали с обеих сторон). Но тогда вы можете увидеть 4 части шириной 16 бит или 2 части шириной 32 бита. Несмотря на то, что у вас могут быть части шириной 8 бит на шине dram, очень маловероятно, что они получают доступ к байту за раз, даже если это возможно.
Поскольку DRAM относительно довольно медленный, вы хотите иметь кэш спереди и хотите, чтобы передачи в dram и из dram были кратны ширине шины за передачу. Таким образом, вы хотите, чтобы строки кэша как таковые и размеры sram каким-то образом совпадали, чтобы эта сторона работала хорошо. И используйте кэш/sram для чтения-изменения-записи по мере необходимости. Хотя вполне возможно, что запись байта может привести к полной выборке строки кэша из dram, затем чтение-изменение-запись в кэш, и эта выборка могла привести к удалению какой-либо другой строки кэша. Такое случается.
Обратите внимание, ни одного упоминания о регистрах. Потому что, что касается памяти, эти две вещи даже отдаленно не связаны. Регистры есть регистры. Система памяти-это система памяти. Инструкции есть инструкции, и соедините их. В общем случае архитектура (arm, mips, x86 и т. Д.) Определяет, Как вы используете регистры для определения адреса, определяет диапазон адресации и т. Д. (Нередко адресное пространство превышает количество битов в регистре общего назначения, сегмент/смещение в первые дни x86).
Затем в соответствии с правилами НАБОРА КОМАНД, а не регистров, определяется, если и как вы создаете байтовые, 16-разрядные, 32-разрядные, 64-разрядные и т. Д. Передачи в/из регистров. Процессор творит свою магию, чтобы справиться с ядром процессора, затем люди с чипами разбираются с материалами на чипе, если таковые имеются, а затем кто-то разбирается со слоями шин/чипов между ядром процессора и самым дальним dram или периферийным устройством. Окончание и другие темы рассматриваются здесь.
Таким образом, 32-разрядная запись в память по адресу 0x1000 считается 32-разрядной записью по адресу 0x1000, но также с точки зрения байтовой адресации эти четыре байта находятся в 0x1000, 0x1001, 0x1002, 0x1003. Они сосуществуют, но имеют отношение к передаче данных на чтение/запись не регистров, не памяти, а правил/определений для адресного пространства и данных в соответствии с набором инструкций. В текущем процессоре он не принимает вашу 32-разрядную запись и не превращает ее в 4 8-разрядные записи по четырем адресам. Это одна запись по одному адресу.
Если позже вы выполните 16 — битное чтение при 0x1000, то это 16-битное чтение при 0x1000. Если затем вы выполните два 8-разрядных чтения в 0x1000 и 0x1001, это будут те же два байта, что и 16-разрядное чтение, и половина байтов из 32-разрядной записи, это просто вопрос адресации в соответствии с правилами набора инструкций. То, что происходит на шине, и то, что происходит в реальных воспоминаниях, может иметь или не иметь никакого представления о наборе инструкций или размере передачи, это следует правилам шины и логики. Система памяти не знает, что такое инструкция, и тем более не заботится о том, какая архитектура, она предназначена для передачи данных различных размеров.
Какой байт 16-битного представления или 32-битного представления находится по адресу 0x1000, соответствует правилам набора команд, и некоторые наборы команд могут изменяться на лету или глобально (можно переключаться между большим и малым конечным, и обратите внимание, что для большого конечного существует более одного определения). Говоря в общем, а не конкретно x86. X86-это немного конечный, поэтому определение хорошо известно. запись от 0x11223344 до 0x1000, если вы прочитаете байт с 0x1001, то получите 0x33.