==================================Outline====================================
메모리 출력 함수 'memory_display'
----------------------------------------------------------------------------
메모리 출력 함수 'memory_display'
메모리를 헥사뷰로 출력하는 함수 'memory_display'를 만들어보자.
//'memory_modify'함수를 복사해서 필요한 부분만 수정하면 편하다.
사용자가 출력하고자하는 메모리의 시작 위치를 입력 받은 후 헥사뷰를 실행시켜 16씩 출력 시킨다. 페이지를 초과하는 경우 사용자로부터 아무키나 입력받으면 다음 페이지를 출력 시키고 ‘q' 혹은 'Q' 입력할 시 출력을 멈춘다.
void memory_display(){
unsigned int uiAddr;
unsigned int uiVal;
char cInput;
while(1)
{
printf("Please input an address to display [%08X - %08X] : ", vpMem_start, vpMem_end);
scanf("%x", &uiAddr);
if('\n'==getchar());
if(uiAddr < (unsigned int)vpMem_start || uiAddr > (unsigned int)vpMem_end)
{
printf("Wrong address \n");
continue;
}
break;
}
while( (uiAddr)< ( (unsigned int)vpMem_end ) )
{
hexaview((void *)uiAddr, 16*16);
uiAddr = uiAddr + (16*16);
if(uiAddr>(unsigned int)vpMem_end)
{
printf("Memory displayed\n");
return;
}
printf("Please enter any to continue(stop for 'Q')\n");
cInput = getch();
if(cInput == 'q' ||cInput == 'Q')
{
printf("Memory display interrupted\n");
return;
}
}
return;
}
헥사뷰 출력 값이 ‘vpMem_end‘를 초과할 경우 해당 자리에서 헥사뷰를 멈추도록 코딩한다.
이를 위해 헥사뷰를 수정한다.
void hexaview(void * vP, unsigned int uiLen)
{
unsigned int uiCnt;
unsigned int uiLine;
printf("===============================================================================\n");
printf(" Address Hexa ASCII \n");
printf("-------------------------------------------------------------------------------\n");
for (uiLine = 0; uiLine < uiLen; uiLine += 16)
{
if(vP > vpMem_end)
return;
printf(" %08X ", vP);
for(uiCnt=0; uiCnt<16; ++uiCnt)
{
if(vP > vpMem_end)
{
while(uiCnt<16)
{
printf(" ");
vP = (char *)vP + 1;
++uiCnt;
}
break;
}
printf("%02X ", *((unsigned char *)vP));
vP = (char *)vP + 1;
}
vP = (char *)vP - 16;
putchar(' ');
for(uiCnt=0; uiCnt<16; ++uiCnt)
{
if(vP > vpMem_end)
{
putchar('\n');
return;
}
if (32 > *((unsigned char *)vP))
{
putchar('.');
}
else if(127 < *((unsigned char *)vP))
{
putchar('.');
}
else
{
printf("%1c", *((unsigned char *)vP));
}
vP = (char *)vP + 1;
}
putchar('\n');
}
putchar('\n');
return;
}
실행시킨 화면은 다음과 같다.
//코딩을 할 때 변수와 함수명의 형식에 일관성이 있어야 한다.
프로그램 실행 함수 ‘program_execute'
로드함수를 사용하여 프로그램을 메모리에 적재한 후, 이것을 실행시키는 ‘program_execute'를 만들어보자. 사용자가 입력하는 명령어는 'GO'이다. 전역 변수를 만들어 주고 로드 상태에 따라 해당 변수의 값을 바꿔준다.
#define LOAD_ON 1
#define LOAD_OFF 0
unsigned int uiLoad;
‘program_execute'가 실행되면 로드 되어 있는 프로그램이 실행되고 난 후 다시 메뉴로 돌아가야 한다. 이를 위해 어셈블리 코드로 만든 ’stst‘, ’ldst‘함수를 사용한다.
레지스터 변수들을 담고 있는 ’context’를 ‘stTempState‘라는 이름으로 선언해준다. 이 구조체는 로드된 프로그램을 실행시키고 다시 메뉴로 돌아갈 수 있게 만들어주는 징검다리 역할을 한다.
구조체의 ‘esp’에는 ‘vpStack’, ‘eip’에는 ‘vpCode’(로드된 프로그램), ‘eax’에는 ‘stOld_state’의 주소를 담아준다.
세팅을 끝낸 ‘stTempState‘를 ’ldst‘의 인자로 전달한다. 'eip'가 적재된 프로그램의 코드 영역을 가리키고 있음으로 프로그램이 실행된다. 프로그램이 수행되고 나면 레지스터를 ’stOld_state’에 저장된 상태로 되돌려 주어야 한다. ‘stOldState’를 'eax'에 넣어준 것이 바로 'stOldState'가 가진 레지스터의 상태로 복구 시켜주기 위함이다.
void program_execute()
{
context stTempState;
if(uiLoad == LOAD_OFF)
{
printf("No loaded program.\nPlease load program by using 'LOAD' command.\n");
return;
}
memset(&stTempState, 0, sizeof(context));
stTempState.esp = (unsigned int)vpStack;
stTempState.eip = (unsigned int)vpCode;
stTempState.eax = (unsigned int)(&stOld_state);
ldst(&stTempState);
printf("System Panic!\n");
return;
}
적재된 프로그램 실행 후 레지스터를 ‘stOldState’의 값으로 복구 시키기 위해 어셈블리로 'init'함수를 만들어준다. C에서도 호환하여 사용하기 위해 언더바(_)를 붙혀준다.
(진행중)
.386
.MODEL FLAT
.code
_start:
_INIT PROC NEAR32
push eax ;'&stOldState' 저장
call _smart
call _t1
call _ldst
_INIT ENDP
'Busan IT > Assembly' 카테고리의 다른 글
String Operation (0) | 2015.10.29 |
---|---|
task switching (0) | 2015.10.29 |
LOAD함수 구현 (0) | 2015.10.23 |
PE구조체 (0) | 2015.10.22 |
memory_modify함수 (0) | 2015.10.20 |