Link to home
Start Free TrialLog in
Avatar of akayed
akayed

asked on

linking objects

i try to link link object that i get after i assemble the assembly source code idon`t know how can i link the obeject with the other object file of my c++ program  
Avatar of while_true
while_true

On what platform do you want to link ? using which compiler ?
Avatar of akayed

ASKER

iam using turbo c++ compiler on windows xp professional there ihave two files one is the object from the source code and other is the object from assembly source code when try to run it gives me error i think it's linking error because when i compile my  file (tempo.cpp) no errors will appear .
 
I'm afraid, that your problem is a problem depending on the c++ name mangling of the c++ compiler (decorated function names): To allow function overloading ( func( int ), func( char *), ...) c++ compilers are 'mangling' the types of function parameters into the function name. Every compiler has its own algorithm to do this. Therefore it is sometimes impossible to link object files/libraries compiled with different compilers.

Which assembler are you using ? Are you calling c++ methods from assembler code ? When you use the MS Macro Assembler, the above described circumstances can cause the the problem when you try to link to borland compiled object files.
Avatar of akayed

ASKER

program called tempo kernel i want to compile this code by c++ compiler in turbo c++

note: all these source codes are in the following site
ftp://ftp.sce.carleton.ca/pub/RealTimeBook/tempo/

// ch2ex1.cpp - a process that prints "Hello, world!"

#include <iostream.h>
#include "tempo.h"

// The root function for the Main process
void Main()
{
    CS(cout << "Hello, world!" << endl);
}
i have all header file that thats the source code need .
i have another code called tempo.cpp  this file contain this code


//
//  tempo.cpp

#include        <iostream.h>
#include        <stdlib.h>
#include           <dos.h>            //setvect() and getvect()
#include        "tempo.h"

const float release = 0.98;


// This points to the single Scheduler object that is created
// by Scheduler::Instance()
Scheduler *Scheduler::InstancePtr = 0;

//----------------------------------------------------------------
// Queue management

inline int QueueLink::empty()
{
      return (next == this);
}

void QueueLink::enqueue(QueueLink *link)
{
      link->prev = prev;
      link->next = this;
      prev->next = link;
      prev = link;
}

QueueLink *QueueLink::dequeue()
{
      QueueLink   *link;

      if (empty())  {
            return (NULL);
      }
      link = next;
      next = link->next;
      link->next->prev = link->prev;
      link->next = link;
    link->prev = link;
      return (link);
}

void QueueLink::remove()
{
      prev->next = next;
      next->prev = prev;
      next = this;
    prev = this;
}

//--------------------------------------------------------------------
// Delta queue management
//

struct DeltaQueueElement {
      PD *Element;
      DeltaQueueElement *Next;
      unsigned int Delta;
};

struct Queue {
      DeltaQueueElement *Head;
};

Queue sleepq;

#define TIMER 8
void interrupt (*oldhandler)(...);
void interrupt timerISR(...);

void InitDeltaQueue(Queue& q)
{
      q.Head = NULL;
}

void DeltaEnqueue(Queue& q, PD *Element, unsigned int Delta)
// Queues up the passed element on the queue.
{
      DeltaQueueElement *NewDeltaElementAt;
      DeltaQueueElement *CurrentDeltaElementAt;
      DeltaQueueElement *OldDeltaElementAt;

      NewDeltaElementAt = new DeltaQueueElement;
      NewDeltaElementAt->Element = Element;
      NewDeltaElementAt->Next = NULL;
      NewDeltaElementAt->Delta = Delta;

      if (q.Head == NULL) {
            // Add element to an empty delta queue
            q.Head = NewDeltaElementAt;
      } else {
            CurrentDeltaElementAt = q.Head;
            OldDeltaElementAt = NULL;

            while ((CurrentDeltaElementAt != NULL) &&
                     (CurrentDeltaElementAt->Delta < NewDeltaElementAt->Delta)) {
                     NewDeltaElementAt->Delta = NewDeltaElementAt->Delta - CurrentDeltaElementAt->Delta;
                     OldDeltaElementAt = CurrentDeltaElementAt;
                     CurrentDeltaElementAt = CurrentDeltaElementAt->Next;
            }
            if (OldDeltaElementAt == NULL) {
                  if (CurrentDeltaElementAt->Delta < NewDeltaElementAt->Delta) {
                        NewDeltaElementAt->Delta = NewDeltaElementAt->Delta - CurrentDeltaElementAt->Delta;
                        NewDeltaElementAt->Next = CurrentDeltaElementAt->Next;
                        CurrentDeltaElementAt->Next = NewDeltaElementAt;
                  } else {
                        CurrentDeltaElementAt->Delta = CurrentDeltaElementAt->Delta - NewDeltaElementAt->Delta;
                        q.Head = NewDeltaElementAt;
                        NewDeltaElementAt->Next = CurrentDeltaElementAt;
                  }
            } else if (CurrentDeltaElementAt == NULL) {
                  OldDeltaElementAt->Next = NewDeltaElementAt;
            } else {
                  CurrentDeltaElementAt->Delta = CurrentDeltaElementAt->Delta - NewDeltaElementAt->Delta;
                  OldDeltaElementAt->Next = NewDeltaElementAt;
                  NewDeltaElementAt->Next = CurrentDeltaElementAt;
            }
      }
}

PD *DeltaDequeue(Queue& q)
// If the delta of the first element of the queue is 0,
// the first element is dequeued and returned;
// otherwise NULL is returned.
{
      DeltaQueueElement *CurrentDeltaElementAt;
      PD *Element;

      Element = NULL;
      CurrentDeltaElementAt = q.Head;
      if (CurrentDeltaElementAt != NULL) {
            if (CurrentDeltaElementAt->Delta == 0) {
                  q.Head = CurrentDeltaElementAt->Next;
                  Element = CurrentDeltaElementAt->Element;
                  delete CurrentDeltaElementAt;
             }
      }
      return Element;
}

void deltaDecrement(Queue& q)
// Decrements the counter of the first element of a delta queue.
{
      DeltaQueueElement *CurrentDeltaElementAt;

      CurrentDeltaElementAt = q.Head;
      if (CurrentDeltaElementAt != NULL) {
            --CurrentDeltaElementAt->Delta;
      }
}

unsigned int DeltaRemoveElement(Queue& q, PD *Element)
{
      unsigned int SearchDone;
      unsigned int Status;
      DeltaQueueElement *PreviousDeltaElementAt;
      DeltaQueueElement *NextDeltaElementAt;
      DeltaQueueElement *CurrentDeltaElementAt;

      Status = 1; // 1 indicates element not found

      CurrentDeltaElementAt = q.Head;
      PreviousDeltaElementAt = NULL;
      SearchDone = (CurrentDeltaElementAt == NULL);
      while (!SearchDone) {
            if (CurrentDeltaElementAt->Element == Element) {
                  Status = 0;  // Element has been found
                  SearchDone = 1;
                  if (PreviousDeltaElementAt == NULL) {
                        q.Head = CurrentDeltaElementAt->Next;
                  } else {
                        PreviousDeltaElementAt->Next = CurrentDeltaElementAt->Next;
                  }
                  NextDeltaElementAt = CurrentDeltaElementAt->Next;
                  if (NextDeltaElementAt != NULL) {
                        NextDeltaElementAt->Delta = NextDeltaElementAt->Delta + CurrentDeltaElementAt->Delta;
                  }
                  delete CurrentDeltaElementAt;
            } else {
                  PreviousDeltaElementAt = CurrentDeltaElementAt;
                  CurrentDeltaElementAt = CurrentDeltaElementAt->Next;
                  SearchDone = (CurrentDeltaElementAt == NULL);
            }
      }
      return Status;
}

//-------------------------------------------------------------
// Scheduler
//
Scheduler::Scheduler()
{
      cout << "Tempo release " << release << endl;
    cout << "Initializing scheduler" << endl;

    InstancePtr = this;
      numprocesses = 0;

      // initialize the sleep queue
      InitDeltaQueue(sleepq);

      CurStackBase = InitStackBase();
      CurStackBase = CurStackBase - INIT_STACK;

      cout << "Creating the idle process" << endl;
      idleProcess = new PD(NULL, IDLE_PRIORITY, IDLE_STACK);
}

//  allocStackSpace() - allocate stack space for a process.
//
char *Scheduler::allocStackSpace(unsigned size)
{
      char *base;

      if (size < MIN_STACK) {
            size = MIN_STACK;
      }
      base = CurStackBase;
      CurStackBase = CurStackBase - size;
      return base;
}

//  addready() - add process p to the list of ready-to-run processes.
//
inline void Scheduler::addready(PD *p)
{
      // add 1 to process priority, because ReadyList[0] is
      // the ready queue for processes with priority -1
      readyList[(p->priority)+1].enqueue(&p->Queue);
}

//  removeready() - remove process p from the list of ready-to-run processes.
//
inline void Scheduler::removeready(PD *p)
{
      p->Queue.remove();
}

// addNewProcess() - called when a new process is created
// to increment the scheduler's count of processes and
// to make the process ready to run.
//
char Scheduler::addNewProcess(PD *p)
{
      numprocesses++;
      p->makeProcessReady();
      addready(p);
      return(TRUE);
}

// removeprocess() - reduce the count of active processes by one
//
void Scheduler::removeprocess()
{
      numprocesses--;
      if (numprocesses == 1) {      // only the null process is left
            terminate_multitasking();
      }
      resched();
}

//  Scheduler::resched()
//  Selects the next ready-to-run process from the RTR list,
//  then performs a context switch to that process.
//
void Scheduler::resched()
{
      PD              *oldProcess;
      PD              *newProcess;
      int             priority;

      for (priority = HIGHEST_PRIORITY;
           priority >= IDLE_PRIORITY;
           --priority) {
            if (!readyList[priority+1].empty()) {
                  newProcess = (PD *)readyList[priority+1].dequeue();
                  break;
            }
      }

      // If calling process is still ready and is the highest
      // priority ready process, just return
      if (newProcess == activeProcess) {
            activeProcess->makeProcessActive();
            return;
      }

      oldProcess = activeProcess;
      activeProcess = newProcess;
      activeProcess->makeProcessActive();
      switchContext(&oldProcess->registers, &activeProcess->registers);
}

//  Scheduler::reliquish()
//  Called by processes when they are ready to give up the
//  processor.  If there are any other ready processes with
//  equal or higher priority than the caller's priority,
//  rescheduling occurs.
//
void Scheduler::relinquish()
{
      short       savedFlags;

      savedFlags = disable_ints();
      activeProcess->makeProcessReady();
      addready(activeProcess);
      resched();
      restore_flags(savedFlags);
}


void Scheduler::startMultiTasking()
{

    // initialize the isr that wakes up sleeping processes
    cout << "Installing timer ISR" << endl;
      oldhandler = getvect(TIMER);
      setvect(TIMER, timerISR);

    cout << "Starting multitasking" << endl;
      removeready(idleProcess);
      activeProcess = idleProcess;
      idleProcess->makeProcessActive();
      relinquish();

      while(TRUE);
}

// Instance() creates an instance of the scheduler,
// but only if no other instances have been created.
// N.B. Calling this function is the only way to
// create a Scheduler object. The constructor for
// class Scheduler is private, so it is not possible to
// instantiate Scheduler objects from outside the class.
// This is based on the singleton pattern in the
// Gang-of-Four book.
void Scheduler::Instance()
{
    if (InstancePtr == 0) {
       InstancePtr = new Scheduler();
    }
}

// Constructor for class PD
//
PD::PD(void (*rootFnPtr)(),
       int Processpriority,
       unsigned stackSize)
       : Queue()
{
      short       *stackPointer;

      // Initialize the stack so that the root function
      // for this process returns to processDone().
      stackPointer = (short*)Scheduler::InstancePtr->allocStackSpace(stackSize);
      *stackPointer =(short)PD::processDone;


      InitPregs(&this->registers, (short)stackPointer, (short)rootFnPtr);

      priority = Processpriority;

      // Init the process' event queues
      for (int i = 0; i < MAX_QUEUES; ++i) {
            eventQueue[i].count= 0;
            eventQueue[i].mask = UNMASKED;
      }
      signaledOn = -1;

      // Ask the scheduler to add this process to its
      // list of ready-to-run processes.
      Scheduler::InstancePtr->addNewProcess(this);
}

//  processDone()
//  When the root function for a process returns, it executes
//  this function.
//
void PD::processDone()
{
      Scheduler::InstancePtr->removeprocess();
}


// create_process() - create a new Tempo process
Process create_process(void (*rootFnPtr)(), int priority)
{
    Process p;
    short savedFlags;

    savedFlags = disable_ints();
    p = new PD(rootFnPtr, priority);
    restore_flags(savedFlags);
    return p;
}

// process_sleep() - the calling process is put
// to sleep for "time" ticks of the system timer
void PD::process_sleep(unsigned int time)
{
      short savedFlags;

      savedFlags = disable_ints();

      if (time > 0) {
            makeProcessSleepBlocked();
            DeltaEnqueue(sleepq, this, time);
            Scheduler::InstancePtr->resched();
      }
      restore_flags(savedFlags);
}

void interrupt timerISR(...)
{
      PD *wakeUp;
      short savedFlags;
      int contextSwitchNeeded;

      // daisy chain to the old timer ISR
      oldhandler();

      // When we return from the old ISR, interrupts
      // have been enabled and EOI has been sent to the
      // PIC. Now check for waiting processes that have
      // timed out and sleeping processes that must be
      // awakened.
      savedFlags = disable_ints();
      contextSwitchNeeded = FALSE;
      PD *active = Scheduler::InstancePtr->activeProcess;
      deltaDecrement(sleepq);
      wakeUp = DeltaDequeue(sleepq);
      while (wakeUp != NULL) {
            if (wakeUp->myState() == SEM_TIMED_BLOCKED) {
                  // A process that is blocked on a
                  // semaphore has timed out. Remove it
                  // from the semaphore queue.
                  wakeUp->Queue.remove();
            }
            wakeUp->timedOut = TRUE;
            wakeUp->makeProcessReady();
            Scheduler::InstancePtr->addready(wakeUp);
            if (wakeUp->priority > active->priority)
                  contextSwitchNeeded = TRUE;

            wakeUp = DeltaDequeue(sleepq);
      }
      if (contextSwitchNeeded) {
            active->makeProcessReady();
            Scheduler::InstancePtr->addready(active);
            Scheduler::InstancePtr->resched();
      }
      restore_flags(savedFlags);
}

// wait() - wait on this process' event queues until one of them is signaled
int PD::wait()
{
      short savedFlags;
      int   i;
      int signaled;

      savedFlags = disable_ints();

      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (eventQueue[i].count > 0)) {    // no need to block waiter
                        eventQueue[i].count--;
                        restore_flags(savedFlags);
                        return i;
            }
      }
      makeProcessQueueBlocked();
      Scheduler::InstancePtr->resched();
      signaled = signaledOn;
      signaledOn = -1;
      restore_flags(savedFlags);
      return signaled;
}

int PD::wait(unsigned int timeout)
{
      short savedFlags;
      int   i;
      int signaled;
    int status;

      savedFlags = disable_ints();
    timedOut = FALSE;
      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (eventQueue[i].count > 0)) {    // no need to block waiter
                        eventQueue[i].count--;
                        restore_flags(savedFlags);
                        return i;
            }
      }
    if (timeout == 0) {
      signaled = TIMED_OUT;
    } else {   // timeout > 0
      DeltaEnqueue(sleepq, Scheduler::InstancePtr->activeProcess, timeout);
      makeProcessQueueTimedBlocked();
      Scheduler::InstancePtr->resched();
      if (timedOut)
          signaled = TIMED_OUT;
      else
          signaled = signaledOn;
    }
      signaledOn = -1;
      restore_flags(savedFlags);
      return signaled;
}

void PD::signal(int queue_number)
{
      short savedFlags;
      PD *active;    // pointer to the currently running process

      if ((queue_number < 0) || (queue_number >= MAX_QUEUES))
            return;

      savedFlags = disable_ints();

      if (((state == QUEUE_BLOCKED) || (state == QUEUE_TIMED_BLOCKED)) &&
            (eventQueue[queue_number].mask == UNMASKED)) {
      if (state == QUEUE_TIMED_BLOCKED)
          DeltaRemoveElement(sleepq, this);
            makeProcessReady();
            signaledOn = queue_number;
            Scheduler::InstancePtr->addready(this);
            if (priority >
                Scheduler::InstancePtr->activeProcess->priority) {
                Scheduler::InstancePtr->activeProcess->makeProcessReady();
                  Scheduler::InstancePtr->addready(
                           Scheduler::InstancePtr->activeProcess);
                Scheduler::InstancePtr->resched();
             }
      } else {
            eventQueue[queue_number].count++;
      }
      restore_flags(savedFlags);
}

void PD::send(int queue, message msg, int ack_queue)
{
      short savedFlags;
      PD *active;    // pointer to the currently running process

      if ((queue < 0) || (queue >= MAX_QUEUES))
            return;

      savedFlags = disable_ints();

      MsgNode *node = new MsgNode;
      node->msg = msg;
      node->ack_queue = ack_queue;
      node->correspondent = Scheduler::InstancePtr->activeProcess;
      eventQueue[queue].enqueue(&node->Queue);

      if (((state == QUEUE_BLOCKED) || (state == QUEUE_TIMED_BLOCKED)) &&
          (eventQueue[queue].mask == UNMASKED)) {
      if (state == QUEUE_TIMED_BLOCKED)
          DeltaRemoveElement(sleepq, this);
            makeProcessReady();
            Scheduler::InstancePtr->addready(this);
            if (priority >
                Scheduler::InstancePtr->activeProcess->priority) {
                Scheduler::InstancePtr->activeProcess->makeProcessReady();
                Scheduler::InstancePtr->addready(
                           Scheduler::InstancePtr->activeProcess);
                Scheduler::InstancePtr->resched();
             }
      }
      restore_flags(savedFlags);
}

int PD::receive(message &msg, Process &correspondent, int &ack_queue)
{
      short savedFlags;
      int   i;
      MsgNode *node;
      int signaled;

      savedFlags = disable_ints();

      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (eventQueue[i].count > 0)) {    // no need to block waiter
                        eventQueue[i].count--;
                        msg = NULL;
                        correspondent = NULL;
                        ack_queue = NULL;
                        restore_flags(savedFlags);
                        return i;
            }
      }
search_again:
      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (!eventQueue[i].empty())) {
                        node = (MsgNode *)eventQueue[i].dequeue();
                        msg = node->msg;
                        correspondent = node->correspondent;
                        ack_queue = node->ack_queue;
                        delete node;
                        restore_flags(savedFlags);
                        return i;
            }
      }
      makeProcessQueueBlocked();
      Scheduler::InstancePtr->resched();
      if (signaledOn != -1) {
            signaled = signaledOn;
            signaledOn = -1;
            msg = NULL;
            correspondent = NULL;
            ack_queue = NULL;
            restore_flags(savedFlags);
            return signaled;
      } else {
            goto search_again;
      }
}

int PD::receive(message &msg, Process &correspondent, int &ack_queue, unsigned int timeout)
{
      short savedFlags;
      int   i;
      MsgNode *node;
      int signaled;

      savedFlags = disable_ints();
    timedOut = FALSE;
      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (eventQueue[i].count > 0)) {    // no need to block waiter
                        eventQueue[i].count--;
                        msg = NULL;
                        correspondent = NULL;
                        ack_queue = NULL;
                        restore_flags(savedFlags);
                        return i;
            }
      }
search_again:
      for (i = 0; i < MAX_QUEUES; i++) {
            if ((eventQueue[i].mask == UNMASKED) &&
                  (!eventQueue[i].empty())) {
                        node = (MsgNode *)eventQueue[i].dequeue();
                        msg = node->msg;
                        correspondent = node->correspondent;
                        ack_queue = node->ack_queue;
                        delete node;
                        restore_flags(savedFlags);
                        return i;
            }
      }
    if (timeout == 0) {
      msg = NULL;
      correspondent = NULL;
      ack_queue = NULL;
      restore_flags(savedFlags);
      return TIMED_OUT;
    } else { // timeout > 0
      DeltaEnqueue(sleepq, Scheduler::InstancePtr->activeProcess, timeout);
      makeProcessQueueTimedBlocked();
      Scheduler::InstancePtr->resched();
      if (timedOut) {
          msg = NULL;
          correspondent = NULL;
          ack_queue = NULL;
          restore_flags(savedFlags);
          return TIMED_OUT;
      }
          if (signaledOn != -1) {
            signaled = signaledOn;
            signaledOn = -1;
                msg = NULL;
            correspondent = NULL;
            ack_queue = NULL;
            restore_flags(savedFlags);
            return signaled;
          } else {
                goto search_again;
      }
    }
}

void PD::maskqueue(int queue_number)
{
      if ((queue_number >= 0) && (queue_number < MAX_QUEUES))
            eventQueue[queue_number].mask = MASKED;
}

void PD::unmaskqueue(int queue_number)
{
      if ((queue_number >= 0) && (queue_number < MAX_QUEUES))
            eventQueue[queue_number].mask = UNMASKED;
}


//  Sem::Sem
//  Constructor for objects of the class Sem
//
Sem::Sem(int initialCount)
{
      count = initialCount;
}

// Called by a process to wait on a semaphore without a timeout
void Sem::wait()
{
      short       savedFlags;

      savedFlags = disable_ints();
      if (count > 0) {
            --count;
      } else {
            // block the caller
            PD* active = Scheduler::InstancePtr->activeProcess;
            active->makeProcessBlocked();
            // move the active process to the
            // semaphore queue
            enqueue(&active->Queue);
            Scheduler::InstancePtr->resched();
      }
      restore_flags(savedFlags);
}

// Called by a process to wait on a semaphore with a timeout
int Sem::wait(unsigned int timeout)
{
      short   savedFlags;
      int      status;

      savedFlags = disable_ints();
      Scheduler::InstancePtr->activeProcess->timedOut = FALSE;
      status = 0;
      if (count) {
            --count;
      } else  if (timeout == 0) {
            status = TIMED_OUT;
      } else {
        PD* active = Scheduler::InstancePtr->activeProcess;
        // time > 0, so block the caller
            // add a pointer to the calling process to the sleep queue
            DeltaEnqueue(sleepq, active, timeout);
            // block the calling process on the semaphore queue
            active->makeProcessSemaphoreTimedBlocked();
            enqueue(&active->Queue);
            Scheduler::InstancePtr->resched();
            if (active->timedOut)
                  status = TIMED_OUT;
      }
      restore_flags(savedFlags);
      return status;
}

//  Signal a semaphore
void Sem::signal()
{
      short savedFlags;
      PD    *p;

      savedFlags = disable_ints();
      if (empty())
      {
            // No processes are blocked on the semaphore
            ++count;
      } else {
            // Get the process at the front of the
            // semaphore queue.
            p  = (PD*)dequeue();

            // If the process specified a timeout
            // when it called wait_semaphore(),
            // remove the process from the sleep queue.
            if (p->myState() == SEM_TIMED_BLOCKED)
                  (void)DeltaRemoveElement(sleepq, p);
            p->makeProcessReady();
            Scheduler::InstancePtr->addready(p);
            if (p->priority >
                  Scheduler::InstancePtr->activeProcess->priority) {
                        Scheduler::InstancePtr->activeProcess->makeProcessReady();
                        Scheduler::InstancePtr->addready(
                              Scheduler::InstancePtr->activeProcess);
                        Scheduler::InstancePtr->resched();
            }
      }
      restore_flags(savedFlags);
}


Semaphore create_semaphore(int initial_count)
{
      Semaphore s;
      short savedFlags;

      savedFlags = disable_ints();
      s = new Sem(initial_count);
      restore_flags(savedFlags);
      return s;
}


Semaphore Tempo_mutex;   // used by the CS macro

// There's not much to this function, because most of the kernel's
// initialization takes place when the scheduler's constructor runs.
void initialize_Tempo()
{
    // create one instance of the scheduler
    Scheduler::Instance();
      Tempo_mutex = create_semaphore(1);
}

void become_idle()
{
      Scheduler::InstancePtr->startMultiTasking();
}

void terminate_multitasking()
{
            cout << "All user processes finished, exiting Tempo" << endl;
            setvect(TIMER, oldhandler);
            exit(0);
}

extern void Main();

Process MainProcess;

//  main()
//
void main()
{
      // initialize kernel data structures
      initialize_Tempo();
      // create the first process from user's Main()
    cout << "Creating Main process" << endl;
      MainProcess = create_process(Main, 0);
      // become the idle process and
      // start the Main process executing
      become_idle();   // this call never returns
}

and i have tempo.h in include file and file called kernel.h .
there are assembly file that i assemble it and i have object from it called machine.obj ,and the source code for this machine.asm
all these file are in this site ftp://ftp.sce.carleton.ca/pub/RealTimeBook/tempo/
i read the readme file i do every thing except the linking because try to do it but ihave erorrs in file tempo.cpp when i try to link the object that i have after i run  the tempo.cpp the errors after running  it i have linking error all files are in bin directory in tc c++
and the header file are in te include directory in tc
 
 
 
ASKER CERTIFIED SOLUTION
Avatar of while_true
while_true

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of akayed

ASKER

when i have all object i try to run  of the ch2ex1 file (this file contain the

main file)  the linking box give it has lines compiled and link pass 2
and 4 errors these errors are :

linker error:undefined symbol _MAIN in module c0.asm
linker error:undefined symbol _TEMPO_MUTEX in module ch2ex1.cpp
linker error:undefined symbol _sem::wait() in module ch2ex1.cpp
linker error:undefined symbol _sem::signal() in module ch2ex1.cpp