{1} | {2} | {3}
{1} -- добавляем количество символов в начало каждой строки (формируем первый столбец)
{2} -- сортируем строки по первому столбцу
{3} -- удаляем первый столбец
Лучшее что можете сделать правильное это купить белый ip у своего провайдера, обычна цена от 50 до 150р в месяц. А вот удобств это добавляет огромную массу и их тяжело будет переплюнуть "бесплатными" вариантами в виде оверлейных сетей или аренды хостингов.
Для правильного вопроса надо знать половину ответа
Всё достаточно просто. У нас целый мегабайт памяти, нам надо 20 бит адреса, а регистры 16-битные.
Для того, чтобы можно было оптимально выделять память, разобьём её на блоки по 220-16 = 16 байт. Пронумеруем эти блоки, получим 16-битные номера.
Теперь для выделения фрагмента памяти мы можем взять номер первого выделяемого 16-байтного блока и количество блоков. Каждый такой выделенный фрагмент памяти назовём сегментом, а номер первого выделяемого блока - адресом сегмента. Внутри сегмента мы можем использовать 16-битную адресацию, что даёт размер сегмента в 64KB.
Но оперативная память ничего не знает о сегментах, ей нужен 20-битный адрес. Поэтому мы берём адрес сегмента, умножаем его на размер блока (16 байт) и прибавляем адрес внутри сегмента.
Наверное стоит обратится к учебнику по Си почему именно так.
Изначально автоматические массивы в Си имели фиксированный размер, т.е. размер надо задавать константой.
Отличие константы от обычной переменной - компилятор в процессе компиляции знает значение константы, а значение переменной нет. В процессе компиляции компилятор может сгенерировать команды для выделения памяти под массив.
Начиная с С99 (это такой стандарт Си от 1999 года) появились VLA (Variable Length Array). Синтаксис такой же как и у обычных массивов, но они могут иметь изменяемый размер, т.е. размер можно задавать обычной переменной.
Использование VLA влечет дополнительные расходы времени выполнения, поэтому многие принципиально не используют эту возможность (например ядро Linux). И это вполне оправданно еще и потому, что память под VLA массивы выделяется на стеке, пространство стека ограничено, а вы с дуру можете там выделить слишком большой массив, что вызовет переполнение стека.
Большинство компиляторов поддерживают VLA, но судя по ошибке, вы используете микрософтовский компилятор. Микрософт никогда не славилась поддержкой стандартов Си. VLA в ее компилятор не завезли до сих пор.
5-й столбец - метки для перехода, 6-й столбец - мнемоники инструкций, 7-й - операнды
Предыдущие столбцы - порядковый номер строки программы и собственно машинные коды операции
Открываете инструкции целевого процессора (который вы не указали, кстати, как и какой именно ассемблер используется) - да интерпретируете...
HALT -команда приостановки процессора до ожидания прерывания
MOV - перенос данных из одного операнда в другое...
и т.п.
В принципе - ничего сложного
При правильном программировании, устройство, висящее на PCI-e, может напрямую общаться с ОЗУ (по DMA) и напрмямую с другим устройством (например, так могут общаться Ethernet- и дисковый контроллеры) на той же шине.
Вероятнее всего проблема связана с тем как компилятор Си упаковывает структуры.
Пока действия происходят внутри сишного кода это не так важно. Но если структура используется для хранения данных в каком нибудь строгом формате следования байтов, или же не явно используется извне, это уже вызывает проблемы.
PS: Сам задал вопрос, сам ответил. Помечать ответ не буду, как-то не красиво получается, да и я не уверен что я прав. Но мне вроде помогло, используя знания из ссылочки выше, смог сделать работающий костыль ( удача? ).