Любите ли вы так Си, как ненавижу его я?

 


После копания в эмуляции Sparc я нашел еще один эмулятор. И принес мне этот эмулятор немало бед и печалек. Решил скомпилировать в Visual Studio, запустил, получил сообщение об отсутствии пакета v142. Как обновить пакет, я не нашел, поэтому запустил установщик. Тот предложил обновление  версии и не показал ничего больше. Выбрал обновление и нажал "Удалить", стал ждать. Через час выяснилось, что вся Visual Studio снесена полностью. Ну и ладно, давно собирался это сделать. Скормил исходники TinyC и получился spark_iss.exe, который требует формат ELF. А как это сделать? Этим вопросом я занялся сегодня. после долгих поисков нашел свалку. Верно, сигавнишники-идеологи не утруждают себя хранением старых версий.

Дальше - получил .ELF, который эмулятору не нравится.GCC тоже не компилирует простой файл:

int main(int argc, char *argv[]) {
int x = 1;
int y = 2;
int z;
z = x + y;
} /* end main() */

Если ничего не помогает, прочтите наконец инструкцию. Прочитал, компилируется так:

set PATH=%PATH%;d:\opt\bin\
sparc-elf-gcc.exe -c -g -o test.o test.c --target=sparc-elf
sparc-elf-ld -g -e 0x0000 -T Cmpwarel.txt -o Test.elf Test.o
pause

Эмулятор схавал файл - вот счастье-то! Сменил компиляцию gcc на ассемблер sparc-elf-as и получил еще один читаемый .elf.

Стал экспериментировать - эмулятор ничего не выдает, но показывает справку ключей. Почитал исходник, в нем используется еще один ключ -r. Запустил - дамп регистров есть, но значения неверные. компилятор LCC подавился. Остался последний шанс - MiniGW Development Studio, который кое-как собрал программу, которая себя странно повела. Сначала влепил говнокод вывода дампа регистров, но вывод в консоль выглядел очень дико. Стал разбираться и нашел слабое звено. Ошибка была тут:

  while ((option = getopt(argc, argv, "f:vdn:b:o:cr")) != EOF)
        switch(option) {
        case 'o':
            if ((fp = fopen(optarg, "wb")) == NULL) {
                fprintf(stderr, "*** main(): Unable to open file %s for writing\n", optarg);
                exit(USER_ERROR);
            }
            break;
        case 'f':
            fname = optarg;
            break;
        case 'c':
            PrintCount  = 1;
            break;
        case 'r':
            DumpRegs    = 1;
        case 'd':
            Disassemble = 1;
            break;
        case 'v':
            verbose = 1;
            break;

у ветки case 'r' не было break, поэтому отладчик показал, что выполнение пройдет и далее и переменной Disassemble присваивается значение 1. В том случае программа выплюнет дизассемблер и вернется обратно из процедуры. добавил код и получил желаемый результат:

Проверил некоторые варианты - работает. Комплект тут. Лучи счастья амбициозной фирмешке.

Комментарии