Переносимость кода C для различных схем адресации памяти
Если я правильно понимаю, DCPU-16 спецификация для 0x10c описывает 16-разрядный адресное пространство, в котором каждое смещение обращается к 16-битовому слову, а не к байту, как в большинстве других архитектур памяти. Это имеет некоторые любопытные последствия, например. Я полагаю, что sizeof(char)
и sizeof(short)
оба возвращают 1
.
Можно ли сохранить C-код переносимым между такими различными схемами адресации памяти? Что было бы страшным иметь в виду?
edit: возможно, я должен был привести более конкретный пример. Скажем, у вас есть сетевой код, который связан с потоками байтов. Вы выбрасываете половину своей памяти, помещая только один байт на каждый адрес, чтобы код оставался прежним, или вы обобщаете все с помощью бит-брейков для обработки N байтов на смещение?
edit2. В ответах, похоже, основное внимание уделяется вопросу о размерах данных, и это не главное - я даже не должен был упоминать об этом. Вопрос заключается в том, как справиться с потерей способности обращаться к любому байту в памяти с помощью указателя. Можно ли ожидать, что код будет агностик в этом вопросе?
Ответы
Ответ 1
Это вполне осуществимо. Грубо говоря, C базовые целочисленные типы данных имеют размеры, которые поддерживают:
sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long)
Вышеупомянутое не совсем то, что говорит спецификация, но оно близко.
Как указано в комментарии к awoodland, вы также ожидаете, что компилятор C для DCPU-16 будет иметь CHAR_BIT == 16
.
Бонус за то, что он не предполагал, что DCPU-16 будет иметь sizeof (char) == 2
, что является обычной ошибкой.
Ответ 2
Когда вы говорите: "теряя способность обращаться к байту", я предполагаю, что вы имеете в виду "бит-октет", а не "char". Портативный код должен принимать только CHAR_BIT >= 8
. На практике архитектуры, которые не имеют байтовой адресации, часто определяют CHAR_BIT == 8
и позволяют компилятору генерировать инструкции для доступа к байту.
Я действительно не согласен с ответами, предлагающими: CHAR_BIT == 16
как хороший выбор. Я бы предпочел: CHAR_BIT == 8
, с sizeof(short) == 2
. Компилятор может обрабатывать сдвиг/маскирование, как и для многих архитектур RISC, для доступа к байтам в этом случае.
Я предполагаю, что Notch пересмотрит и уточнит спецификацию DCPU-16; уже есть запросы на механизм прерывания и дальнейшие инструкции. Это эстетичный фон для игры, поэтому я сомневаюсь, что в ближайшее время появится официальная спецификация ABI. Тем не менее, кто-то будет работать над этим!
Edit:
Рассмотрим массив из char
в C. Компилятор упаковывает 2 байта в каждый собственный 16-разрядный word
из памяти DCPU. Поэтому, если мы получим доступ, скажем, к 10-му элементу (индекс 9
), выберем слово # [9/2] = 4 и извлеките байт # [9% 2] = 1.
Пусть "X" - начальный адрес массива, а "I" - индекс:
SET J, I
SHR J, 1 ; J = I / 2
ADD J, X ; J holds word address
SET A, [J] ; A holds word
AND I, 0x1 ; I = I % 2 {0 or 1}
MUL I, 8 ; I = {0 or 8} ; could use: SHL I, 3
SHR A, I ; right shift by I bits for hi or lo byte.
Регистр A
содержит "байт" - это 16-битный регистр, поэтому верхнюю половину можно игнорировать.
Альтернативно, верхняя половина может быть обнулена:
AND A, 0xff ; mask lo byte.
Это не оптимизировано, но оно передает идею.
Ответ 3
Равновесие выглядит примерно так:
1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
Тип short
может быть 1
, и на самом деле, возможно, вы даже захотите, чтобы тип int
тоже был 1
(я не читал спецификацию, но я " m, предполагая, что тип данных обычный - 16 бит). Этот материал определяется компилятором.
Для практичности компилятор может захотеть установить long
на нечто большее, чем int
, даже если ему требуется компилятор, выполняющий дополнительную работу (например, внедрение сложения/умножения и т.д. в программном обеспечении).
Это не проблема адресации памяти, а вопрос детализации.
Ответ 4
да, вполне возможно передать код C
с точки зрения передачи данных было бы целесообразно либо упаковать биты (или использовать сжатие), либо отправить в 16-битные байты
потому что процессор почти полностью общается только с (игровыми) внутренними устройствами, которые, вероятно, также будут все 16 бит, это не должно быть реальной проблемой
Кстати, я согласен, что CHAR_BIT
должен быть 16 как (IIRC), каждый char должен быть адресуемым, поэтому make CHAR_BIT ==8
будет ТРЕБУЕТСЯ sizeof(char*) ==2
, что сделает все остальное сложным