Переносимость кода 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, что сделает все остальное сложным