Как правильно менять параметры программы
Date: 02/24/06
(Code WTF) Keywords: software
Что бы это значило?
* ((unsigned int *) 0х4fffff0) = 0х12345678;
* ((unsigned int *) 0х4fffff4) = 0х03600000; // МЕ_VECTORS;
У нас есть программа. Бежит на bare metal, никакой ОС. Немаленькая, жрет 30М, одних инструкций 6М. Работает с видеокамерой. Получает сообщения через USB. Например, изменить какой-нибудь параметр.
Изменять параметры не так-то просто - пойди пойми, кто их успел запомнить и уже настроился работать некоторым образом. И вдруг все поменялось? Довольно обидно.
К счастью, у этой проблемы есть отличное решение: перезапустить процесс. Однако у нас системы нет, а значит, нет и процессов. Зато каждый может организовать software reset. Черкнул хексой по известному адресу - и все дела.
Так что же - по адресу 0х4fffff0 живет reset register? Нееет! В регистр как раз пишут с помощью специальной функции. Но этого мало. Надо еще сказать КОНЧЕННОМУ boot loader-у, где же все-таки entry point.
Ежу понятно, что 0х4fffff0 - конец внутренней памяти, что туда надо записать 0х12345678, дабы бут лоадер осознал, что это с ним разговаривают, и что 0х03600000 - КАК ПРАВИЛО, адрес энтри пойнта.
Однажды перед дэдлайном при изменении параметров программа начала падать. Линкер скрипт поменялся, и энтри пойнт куда-то сдвинулся.
Я переписал мега-фрагменты следующим образом:
* ((unsigned int *) 0x4fffff0) = 0x12345678;
* ((unsigned int *) 0x4fffff4) = (unsigned int)&ME_vectors; // ME_VECTORS;
Заработало.
Почему автор не осилил этого сам? Будучи экспертом в ассемблере, он декларировал:
extern unsigned int ME_vectors; //ясен пень, первая комманда функции - ОТЛИЧНОЕ ЦЕЛОЕ ЧИСЛО!
А также не поставил `&', когда брал адрес. В ассемблере все глобальные переменные - указатели. В C получилось, что берется первая инструкция вместо адреса. Тогда наш спец нашел решение: поглядел, где энтри пойнт, и хексой его, ХЕКСОЙ!!
Source: http://community.livejournal.com/code_wtf/30388.html