Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [C/C++ $ ASM] Undefined reference to ... 
V
    Опции темы
Letov
Дата 30.5.2008, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 321
Регистрация: 22.2.2007
Где: Санкт-Петербург

Репутация: 4
Всего: 4



Доброго времени суток! Недавно достал одну книжечку по написанию операционных систем, где встретил такой код
kernel.c
Код

#include "intslib.c"
#include "ioports.c"
#include "handlers.c"
void kernel_main()
{
 init_interrupts();
 init_tty();
 clear();
 puts("We use C, isn't this great?\n");
 
 for(;;);
}


handlers.c
Код

#include "scancode.h"
#define IRQ_HANDLER(func) void func (void);\
 asm(#func ": pusha \n call _" #func " \n movb $0x20, %al \n outb %al, $0x20 \n popa \n iret \n");\
 void _ ## func(void)



IRQ_HANDLER(irq_timer)
{
  
}

//Здесь мы храним состояние шифта
char shift = 0;

IRQ_HANDLER(irq_keyboard)
{
  unsigned char scancode, ascii;
  unsigned char creg;

  //Прочитаем скан-код из порта 0x60
  scancode = inportb(0x60);
  
  switch(scancode) {
    
    //Скан-коды нажатого шифта
  case 0x36: 
  case 0x2A:
    shift = 1;
    break;

    //Скан-коды отпущенного шифта
  case 0x36 + 0x80:
  case 0x2A + 0x80:
    shift = 0;
    break;
    
  default:
  //Если клавиша отпущена...
    if(scancode >= 0x80) {
    //То ничего не делать      
    
    } else {
    //А если нажата...
  
      if(shift){
      //Если шифт нажат, но преобразовать скан-код в "шифтнутое" ASCII
    ascii = scancodes_shifted[scancode];

      } else {
      //А если не нажат - то в обычное
    ascii = scancodes[scancode];
      }
      
      //Если в результате преобразования нажата клавиша с каким-либо
      //символом, то вывести его на экран
      if(ascii != 0) {
    putchar(ascii);
      }
    }
    break;
  }

  //Считаем байт состояния клавиатуры
  creg = inportb(0x61);
  
  //Установим в нем старший бит
  creg |= 1;

  //И запишем обратно
  outportb(0x61, creg);
}

void init_interrupts()
{
  i_install(0x20, &irq_timer, 0x8e);
  i_install(0x21, &irq_keyboard, 0x8e);
  i_setup();
  i_enable();
}


intslib.c
Код

/* 
  intslib.c 
*/

#define IDT_TABLE 0x100000
#define IDT_REG 0x100800
#define SYS_CODE_SELECTOR 0x8

//Функция i_install() устанавливает в качестве обработчика vector функцию func. 
//Тип шлюза (прерывания [0x8e] или ловушки [0x8f]) указывается параметром type.

//Фактически, эта функция создает (или изменяет) соответствующий дескриптор в таблице IDT

void i_install(unsigned char vector, void (*func)(), unsigned char type) 
{
  char * idt_table=IDT_TABLE;
  
  unsigned char i;
  unsigned char b[8];

  b[0]=  (unsigned int)func & 0x000000FF;
  b[1]=( (unsigned int)func & 0x0000FF00) >> 8;
  b[2]=SYS_CODE_SELECTOR;
  b[3]=0;
  b[4]=0;
  b[5]=type;
  b[6]=( (unsigned int)func & 0x00FF0000) >> 16;
  b[7]=( (unsigned int)func & 0xFF000000) >> 24;

  
  
  for(i=0;i<8;i++){
    *(idt_table+vector*8+i)=b[i];
  }
  
  
}

//Функция i_setup() загружает регистр IDTR
void i_setup()
{
  unsigned short *table_limit = IDT_REG;
  unsigned int *table_address = IDT_REG+2; 

  *table_limit = 256*8 - 1;
  *table_address = IDT_TABLE;

  asm("lidt 0(,%0,)"::"a"(IDT_REG));
  asm("sti");
}


//Включение обработки прерываний
void i_enable()
{
  asm("sti");
}

//Отключение обработки прерываний
void i_disable()
{
  asm("cli");
}


Ошибка имеет вид:
Undefined reference to 'irq_timer'
Undefined reference to 'irq_keyboard'
Undefined reference to 'irq_timer'

Подскажите, пожалуйста, как избавиться от данной ошибки (sarry за нубский вопрос=).
Код, по идее, должен быть правильным, но ошибка "на лицо". Пользуюсь для компиляции gcc. Линкую с помощью ld. Скорее всего ошибку дает он!

Заранее спасибо!

Это сообщение отредактировал(а) Letov - 30.5.2008, 22:29


--------------------
Не бывает плохих языков программирования. Бывают плохие программисты...

PM MAIL   Вверх
opjox
Дата 30.5.2008, 22:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 90
Регистрация: 17.1.2008

Репутация: 11
Всего: 14



Нигде не вижу объявление irq_timer и irq_keyboard
PM MAIL ICQ   Вверх
Letov
Дата 30.5.2008, 22:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 321
Регистрация: 22.2.2007
Где: Санкт-Петербург

Репутация: 4
Всего: 4



Так это понятно, но я тут немного разобрался и получилось: gcc компилит без ошибок, а вот ld линкер выдает эти ошибки. Я пытаюсь линкером объединить несколько файлов с параметром -Ttext 0x200000.


--------------------
Не бывает плохих языков программирования. Бывают плохие программисты...

PM MAIL   Вверх
opjox
Дата 31.5.2008, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 90
Регистрация: 17.1.2008

Репутация: 11
Всего: 14



Цитата(Letov @  30.5.2008,  22:42 Найти цитируемый пост)
Так это понятно

Извиняюсь, ступил – не посмотрел на реализацию макроса. Кстати, ошибка в нем, точнее от его использования. 

Для простоты объяснения, я опущу строку в макросе с ассемблерной вставкой, т.е. преобразую к следующему виду:
Код

#define IRQ_HANDLER(func) void func (void);\
                          void _ ## func(void)


Теперь рассмотрим, что получим от такого вызова:

Код

IRQ_HANDLER(irq_timer)
{
}


После обработки кода препроцессором мы получим такой код:

Код

void func(void);      // замечу, что именно func, а не irq_timer. [ошибка 1] 
void _irq_timer(void)
{

}


Выходит, что у нас после этого есть только объявленный прототип функции func и нигде нет ее реализации, а также _irq_timer (объявленная и определенная)
А позже мы пытаемся узнать адрес несуществующей функции &irq_timer в 76 строчке. 

Как именно подправить эти ошибки зависит от того, что вы в итоге хотите получить. 

PM MAIL ICQ   Вверх
Letov
Дата 31.5.2008, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 321
Регистрация: 22.2.2007
Где: Санкт-Петербург

Репутация: 4
Всего: 4



В том то и дело, что когда компилирую через gcc - ни одной ощибки нету, а вот когда линкую с другими бинарниками - вылезает ошибка (в прикрепленном файле). Т.е. компилятор нормально реагирует на макрос, а вот линкер на полученный бинарник - нет.

А получить мне нужно обработчик прерывания irq1 и irq0, который функцией i_install() заносится в таблицу прерываний.

Может надо так:
Код

#define IRQ_HANDLER(func) void ## func (void);\
                          void _ ## func(void)


Присоединённый файл ( Кол-во скачиваний: 10 )
Присоединённый файл  _______1.png 5,62 Kb


--------------------
Не бывает плохих языков программирования. Бывают плохие программисты...

PM MAIL   Вверх
Letov
  Дата 1.6.2008, 12:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 321
Регистрация: 22.2.2007
Где: Санкт-Петербург

Репутация: 4
Всего: 4



Все, спасибо за отет. Разобрался! Дело вроде в макросе:
Код

#define IRQ_HANDLER(func) void func (void)\
 {asm(#func ": pusha \n call _" #func " \n movb $0x20, %al \n outb %al, $0x20 \n popa \n iret \n");}\
 void _ ## func(void)


Это сообщение отредактировал(а) Letov - 1.6.2008, 13:10


--------------------
Не бывает плохих языков программирования. Бывают плохие программисты...

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.0464 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.