2012-05-16 4 views
1

(글쎄, 여기 처음 질문 할 때 영어가 제 첫 번째 언어가 아니므로 제 실수를 용서하십시오.) 그리고 나는 프로그램에서 친환경적입니다 .)인라인 어셈블러를 사용하여 레지스터 값을 저장하는 방법

OS 숙제를하면서이 문제를 만났습니다. SwitchToFiber을 시뮬레이트하라는 질문을 받았으며, 다음 번에 기능을 복구하기 위해 레지스터 값을 저장하는 방법을 모르겠다. 라고 불렀다.

제 문제가 명확한 지 모르겠습니다. 내 코드가 유용하다고 생각하지는 않지만 아래에 설명하겠다. 내가 어떤 부분이 아마 유용 모르기 때문에

#include <stdio.h> 

#define INVALID_THD NULL 
#define N 5 
#define REG_NUM 32 
unsigned store[N][REG_NUM]; 
typedef struct 
{ 
    void (*address) (void * arg); 
    void* argu; 
}thread_s; 

thread_s ts[N]; 

void StartThds(); 
void YieldThd(); 
void *CreateThd(void (*ThdFunc)(void*), void * arg); 
void thd1(void * arg); 
void thd2(void * arg); 
void StartThds() 
{ 

} 

void YieldThd() 
{ 
    thd2((void*)2); 

} 

void *CreateThd(void (*ThdFunc)(void*), void * arg) 
{ 
    ts[(int)arg].address = (*ThdFunc); 
    ts[(int)arg].argu = arg; 
} 

void thd2(void * arg) 
{ 
    for (int i = 4; i < 12; i++) 
    { 
     printf("\tthd2: arg=%d , i = %d\n", (int)arg, i); 
     //in order to see clearly,i added /t abouve 
     YieldThd(); 
    } 
} 

void thd1(void * arg) 
{ 
/* 
    __asm__(

    ); 
*/ 
    for (int i = 0; i < 12; i++) 
    { 
     printf("thd1: arg=%d , i = %d\n", (int)arg, i); 
     YieldThd(); 
    } 
} 

int main() 
{ 
    //this is my first plan, to store the register value in some static arry 
    for(int i = 0; i<N; i++) 
     for(int j = 0; j<REG_NUM; j++) 
      store[i][j] = 0; 
    //create the two thread 
    if (CreateThd(thd1, (void *)1) == INVALID_THD) 
    { 
     printf("cannot create\n"); 
    } 
    if (CreateThd(thd2, (void *)2) == INVALID_THD) 
    { 
     printf("cannot create\n"); 
    } 


    ts[1].address(ts[1].argu);  //thd1((void*)1),argu = 1; 
// StartThds(); 
    return 0; 
} 

이 전체 코드는 지금은,이, 그래서 위의 모두 넣어. 보시다시피, 대부분은 여전히 ​​비어 있습니다.

+0

어떤 CPU에 대해 이야기하고 있습니까? 그리고 어셈블리 코드는 어디에 있습니까? Btw, 이것은 C의'setjmp()'/'longjmp()'(힌트) 구현과 매우 흡사합니다. –

+0

글쎄, 내 CPU는 Pentium4 인 것 같다. 그리고 나는 C-FREE 컴파일을 사용하고있다. 내 어셈블리 코드를 시작하는 방법조차 모른다. 그래서 아무 것도 없다. – shellbye

+0

그런 다음 몇 가지 어셈블리를 배우고 특정 질문으로 돌아 오는 방법은 무엇입니까? –

답변

1

이 경우 어셈블리를 작성할 필요가 없다는 점을 주석에서 지적한 것처럼 setjmp()/longjmp()을 사용하여 빠져 나와 필요한 상태 저장을 수행 할 수 있습니다.

+0

사용자 수준의 스레드를 만든 다음 일정을 시뮬레이트 할 계획 이었지만 선생님은 'setjmp()/longjmp()'만으로는 충분하지 않으며 assebly를 사용하여 레지스터를 저장해야한다고 말했습니다. – shellbye

+0

그가 2 개의 스레드 사이를 전환하는 경우에만. 3 인 경우 자신을 저장/복원해야합니다. – RedX

+0

그래, 내가 원하는 것은 2 개 이상을 시뮬레이션 할 수 있기 때문에 assebly는 필요하다고 생각하지만 어떻게해야할지 모르겠다. – shellbye

0

나는 이것을 전에했지만 나는 항상 세부 사항을 찾아야했다. 다음은 물론 의사 코드입니다.

typedef struct regs { 
    int ebx; //make sure these have the right size for the processors. 
    int ecx; 
    //... for all registers you wish to backup 
} registers; 

//when changing from one thread 
asm(//assembly varies from compiler to compiler check your manual 
    "mov ebx, thread1.register.ebx; 
    mov ecx, thread1.register.ecx;" 
    // and so on 

    //very important store the current program counter to the return address of this fu nction so we can continue from ther 
    // you must know where the return address is stored 
    "mov return address, thread1.register.ret" 
); 

//restore the other threads registers 
asm(
    "mov thread2.register.ebx, ebx; 
    mov thread2.register.ecx, ecx; 
    //now restoer the pc and let it run 
    mov thread2.register.ret, pc; //this will continue from where we stopped before 
); 

이 어떻게 작동하는지의 더 많거나 적은 원칙 :

은 기본적으로 당신이 당신이 당신의 레지스터와 구조체를 만드는 것입니다. 당신이 이것을 배우고 있기 때문에 나머지는 스스로 알아낼 수 있어야합니다.

+0

당신의 지시에 진심으로 감사드립니다! 나는 그것을하기 위해 최선을 다할 것입니다. – shellbye

관련 문제