Busan IT/Assembly2015. 11. 3. 17:36

==================================Outline====================================

Bit Manipulation

Shift and Rotate Instructions

----------------------------------------------------------------------------

  

p/259

 

Converting a 2' Complement Integer to an ASCII string

 

아는 것임으로 패스

 

 

p/267

 

Bit Manipulation

 

다 아는 것임으로 넘어간다....

 

클럭 사이클이 메모리가 개입하면 눈에 띄게 커지는 것을 알 수 있다.

 

‘test'명령어는 결과 값이 accumulator 레지스터에 들어가는 것과는 제외하는 ’and' 연산과 동일하다. 'test'는 명령어는 특정 비트의 값을 확인하거나 추출하기 위해서 사용된다.

 

test dx, 2000h ; check bit 13

 

Shift and Rotate Instructions

 

p/278

h(로직): 쉬프트를 사용하면 빈 자리는 무조건 ‘0’으로 채워진다.

a(연산): 음수/양수를 판별하여 음수일 경우 빈자리를 ‘1’, 양수일 경우 ‘0’으로 채워준다.

 

예제를 통해 확인해 보자.



쉬프트 연산의 사이클은 곱셈과 나눗셈에 비해 낮기 때문에 2의 제곱의 곱셈과 나눗셈에서는 쉬프트 연산을 사용하는 효율적이다.

 


 

operand3개인 쉬프트연산도 사용할 수 있다.

//해당 명령어가 존재한다는 것만 알고 있자.

 



 

 

반응형
Posted by newind2000
Busan IT/Assembly2015. 11. 3. 12:53

==================================Outline====================================

String Instruction

- stos

- lods

Character Translation

- xlat

----------------------------------------------------------------------------

교재 p/249

 

stos

 

같은 문자를 반복하여 저장한다.

 

lods

 

‘esi’에 있는 문자열을 'eax'에 저장한다.

 

 

Character Translation

 

교재 p/254

 

xlat

 

'EBX' 문자열이 시작하는 주소를 가리키고 ‘AL’에서 배열의 값을 가지고 있는 상황에서 'AL'에 해당 값이 들어가게 된다.

 

 

[Figure 7.13 Translation program]



 

 /*** 소스 ***/


.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h
cr  equ   0dh
Lf  equ   0ah

.STACK 4096

.DATA
string     BYTE   'This is a #!$& STRING'0
strLength  EQU  $ - string - 1
label1     BYTE   "Original string  ->"0
label2     BYTE   cr, Lf, "Translated string"0
crLf     BYTE   cr, Lf, 0
table     BYTE   48 DUP (' '), '0123456789'7 DUP (' ')
    BYTE   'abcdefghijklmnopqrstuvwxyz'6 DUP (' ')
    BYTE  'abcdefghijklmnopqrstuvwxyz'133 DUP (' ')

.CODE
_start:    output   label1
    output   string
    output   crlf
    mov   ecx, strLength
    lea  ebx, table
    lea  esi, string
    lea  edi, string

forIndex:  lodsb
    xlat
    stosb
    loop  forIndex
    
    output label2
    output string
    output crlf

    INVOKE ExitProcess, 0
PUBLIC _start

 

 

 

 

 

 

 

 

 

 

반응형
Posted by newind2000
Busan IT/Assembly2015. 11. 2. 08:52

==================================Outline====================================

Repeat Prefixes and More String Instructions

----------------------------------------------------------------------------

 

Repeat Prefixes and More String Instructions

 

p/239

 

 

'rep' 명령어는 ‘ecx’ 레지스터를 카운터로 사용한다.

 

'rep'를 풀어서 쓰면 다음과 같다.

 

rep movsb

 

jecxz endCopy ;skip loop if count is zero

 

copy: movsb ;move 1 character

loop copy ;decrement count and continue

 

endCopy:

'ecx' 값은 'rep' 명령어 operand가 수행되기 전에 0인지 확인되고 'ZF'플래그는 operand가 수행되고 나서 검사가 된다.

 

첫 번째 문자가 같지 않으면 'ecx'값과 ‘ZF' 값이 동시에 0이 아님으로 ’repz'명령어는 멈추게 된다.

 

//‘repz’/‘repe’는 같은 명령어이다.

교재 p/244 String search program



[sca.asm]


.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h
cr  equ   0dh
Lf  equ   0ah

.STACK 4096

.DATA
prompt1    BYTE   "String to search? "0
prompt2    BYTE   cr, Lf, "Key to search for? "0
target    BYTE  80 DUP (?)
key    BYTE  80 DUP (?)
trgtLength  DWORD  ?
KeyLength  DWORD  ?
lastPosn  DWORD  ?
failure    BYTE  cr, Lf, Lf, "The key does not appear in the string.", cr, Lf, 0
success    BYTE  cr, Lf, Lf, "The key appear in the string."
position  BYTE  11 DUP (?)
    BYTE  " in the string.", cr, Lf, 0

PUBLIC _start
.CODE

_start:    output   prompt1  ;
    input  target,  80 ;
    lea  eax,  target ;
    push  eax ;
    call  strlen ;
    mov  trgtLength,  eax;
    output  prompt2 ;
    input   key, 80 ;
    lea  eax,  key ;
    push  eax ;
    call  strlen ;
    mov  keyLength, eax ;

    mov  eax, trgtLength ;
    sub  eax, keyLength ;
    inc   eax ;
    mov lastPosn,  eax ;
    cld

    mov  eax, 1 ;

whilePosn:  cmp  eax, lastPosn ;
    jnle  endWhilePosn ;

    lea  esi, target ;
    add   esi, eax ;
    dec  esi ;
    lea  edi, key ;
    mov  ecx, keyLength ;
    repe  cmpsb ;
    jz  found ;
    inc  eax ;
    jmp  whilePosn ;
endWhilePosn:
    output  failure ;
    jmp  quit ;

found:    dtoa  position, eax ;
    output   success ;
quit:
    INVOKE ExitProcess,  0 ;

strlen    PROC  NEAR32 ;

    push  ebp ;
    mov  ebp, esp ;
    pushf ;
    push  ebx ;
    sub  eax, eax ;
    mov  ebx,  [ebp+8] ;

whileChar:  cmp  BYTE PTR [ebx], 0 ;
    je  endWhileChar ;
    inc   eax ;
    inc  ebx ;
    jmp  whileChar ;

endWhileChar:
    pop  ebx ;
    popf ;
    pop  ebp ;
    ret  4

strlen    ENDP

    END

 

 

 

 


반응형
Posted by newind2000
Busan IT/Assembly2015. 10. 29. 17:35

==================================Outline====================================

String Operation

----------------------------------------------------------------------------

 

String Operation

 

교재 p/232

 

문자열과 관련된 명령어는 5개가 있다.

 

movs(move string)

cmps(compare string)

scas(scan string)

stos(store string)

lods(load string)

 

1byte 단위로 명령어를 내릴 때는 뒤에 첨자 'b'가 붙고, 2byte‘w', 4byte’d'가 붙는다.

 

어셈블리에서의 string은 문자열이 아닌 배열을 뜻한다.

문자열을 사용할 때는 레지스터 'ESI'와 'EDI'가 사용된다.

 

ESI = Extended Source Index

EDI = Extended Destination Index

 

'movs'명령어는 메모리에서 메모리로 데이터를 복사함으로 4사이클이 소모된다.

  

 

 

'movs' 명령어는 한 번에 한 단위 원소만을 조작시키고 명령어가 수행되고 나면 'esi'‘edi'는 조작 단위만큼 이동하게 되는데 이 때 ’EFL‘레지스에 ’DF‘ 플래그가 0일 때는 주소 값이 증가하고 1일 때는 주소 값이 감소하게 되는데 'DF'플래그의 값은 'cld', 'std'명령어로 조작할 수 있다.

문자열을 복사하는 함수를 만들어보자.

 

//함수를 사용하고 나서는 사용하기전의 레지스터 상태로 원상복구 시켜 주어야 한다.

 

교재 p/234


[strcpy.asm]

.386
.MODEL FLAT
ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD
INCLUDE io.h
cr  equ   0dh
Lf  equ   0ah

.STACK 4096

.DATA
prompt    BYTE  cr, Lf, "Original string? ",0
stringIn  BYTE  80 DUP (?)
display    BYTE  cr, Lf, "Your string was...", cr, Lf
stringOut  BYTE  80 DUP  (?)

.CODE
_start:  output   prompt
  input  stringIn,   80
  lea  eax,    stringOut
  push  eax
  lea  eax, stringIn
  push  eax
  call   strcopy
  output  display
  INVOKE  ExitProcess,  0

PUBLIC  _start

strcopy    PROC NEAR32

  push  ebp
  mov  ebp, esp

  push edi
  push esi
  pushf

  mov  esi, [ebp+8]
  mov  edi, [ebp+12]
  cld

whileNoNull:
  cmp  BYTE PTR [esi],  0
  je  endWhileNoNull
  movsb
  jmp  whileNoNull

endWhileNoNull:
  mov BYTE PTR [edi], 0

  popf
  pop  esi
  pop  edi
  pop  ebp
  ret  8

strcopy  ENDP

  END

 

 


반응형
Posted by newind2000
Busan IT/Assembly2015. 10. 29. 09:43

==================================Outline====================================

task switching

----------------------------------------------------------------------------

지금까지 코딩한 내용을 다시 한번 훑어보자.

 

컴퓨터를 구동하기 위한 OS가 존재하고 그 OS안에서 동작하는 OS프로그램을 만든다.

 

//code 영역은 오직 읽기만 가능한 영역이다.

 

여러 가지 프로그램을 수행할 때 메모리가 모자라게 되면 하드드라이브를 사용하게 된다. 이 때 메모리에 멤버를 하나 더 선언하여 하드드라이브의 주소를 저장해주면 된다.

 



task switching.zip

 

 

반응형

'Busan IT > Assembly' 카테고리의 다른 글

Repeat Prefixes and More String Instructions  (0) 2015.11.02
String Operation  (0) 2015.10.29
메모리 출력 함수 'memory_display' 프로그램 실행 함수, ‘program_execute'  (0) 2015.10.24
LOAD함수 구현  (0) 2015.10.23
PE구조체  (0) 2015.10.22
Posted by newind2000
Busan IT/Assembly2015. 10. 24. 00:12

==================================Outline====================================

메모리 출력 함수 'memory_display'

프로그램 실행 함수  ‘program_execute'

----------------------------------------------------------------------------

메모리 출력 함수 '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, 0sizeof(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


init.asm


smart.c



반응형

'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
Posted by newind2000
Busan IT/Assembly2015. 10. 23. 11:46

==================================Outline====================================

LOAD함수 구현

----------------------------------------------------------------------------

 

LOAD함수를 사용하여 실행 파일을 동적할당 받은 메모리에 올린다. 헥사뷰를 사용하여 메모리의 어떻게 적재 되어 있는지 확인해 본다.

 

LOAD함수가 실행되면 우선 사용자로부터 실행파일명을 입력 받고 파일이 존재하는지 검사 후 파일이 존재하면 파일을 동적 할당 받은 메모리에 적재한다.

 

프로그램 적재 후 코드와 데이터 영역을 따로 메모리에 적재하는데 이 때 각 영역의 주소를 알아내기 위해서 PE 파일 포맷에 대해 알아야 한다.

 

해당 블로그에 자세한 설명이 나와 있음으로 참고한다.

 

http://haerakai.tistory.com/18

 

 

우선 PE 파일 포맷의 전체적인 구조를 살펴보자.

헤더와 섹션으로 구분이 되어 있다. 헤더 부분은 각 섹션에 대한 주요 정보를 담고 있으며 헤더의 정보를 참조하여 각 섹션으로 이동할 수 있다.

 

우선 IMAGE_DOS_HEADER를 살펴보자.

 

//구조체의 원형은 Windows.h에 담겨 있음으로 헤더파일을 추가한다.

 

//#include <Windows.h>

다음 섹션으로 넘어가기 위해 보아야 할 구조체의 멤버는 ‘e_lfanew'이다. 4byte로 되어 있으며 다음 헤더의 주소를 담고 있다.

 

이를 통해 다음 헤더인 IMAGE_INT_HEADER로 이동한다.

Signature4byte임으로 이를 포인터의 주소를 4byte이동 시킨 후 IMAGE_FILE_HEADER를 가리키게 한다.

IMAGE_FILE_HEADER의 멤버인 SizeOfOptionalHeader에 말 그대로 Optional_Header의 크기가 담겨져 있다. 이를 활용하여 Optional_Header의 주소에서 Optional_Header의 크기만큼을 더하면 SECTION_TABLE로 넘어갈 수 있다.

SECTION헤더에서 각 헤더에 대한 크기와 위치가 저장되어 있다. 이것을 활용하여 원하는 섹션의 위치에 데이터를 집어 넣으면 된다.





/*** 코드 ***/


void load()
{
  int iFd;
  char cBuf[CMD_SIZE];
  int iRtn;
  IMAGE_DOS_HEADER *stpDosH;
  IMAGE_NT_HEADERS32 *stPNtH;
  IMAGE_SECTION_HEADER *stSH;
  unsigned int iAddr;
  unsigned int uiNH;
  IMAGE_FILE_HEADER * stpFH;
  unsigned int uiSizeofOH;
  //IMAGE_OPTIONAL_HEADER * stpOH;
  unsigned int uiOHaddr;
  IMAGE_SECTION_HEADER * stpSHt;  
  unsigned int uiPRDt;
  unsigned int uiSRDt;
  IMAGE_SECTION_HEADER * stpSHd;
  unsigned int uiPRDd;
  unsigned int uiSRDd;  
  
  printf("읽어 들일 파일명을 입력하세요.\n");
  iRtn = read(0, cBuf, CMD_SIZE);
  if(iRtn < 2)
  {
    return;  
  }  
  cBuf[iRtn-1= 0;
  
  iFd = open(cBuf, O_RDONLY|O_BINARY, 666);
  if(iFd== 0)
  {
    printf("[%s]을 사용할 수 없습니다.\n", cBuf);
    return;
  }
  
  iRtn = read(iFd, vpMem_start, MAX_PRG_SIZE);
  if(iRtn== 0)
  {
    printf("파일을 불러올 수 없습니다..\n");
    return;
  }
  printf("------------------ LOAD PROCEDURE ------------------\n"); 
  printf("vpMem_start         [%08X]\n", vpMem_start);

  
  stpDosH = (IMAGE_DOS_HEADER *)vpMem_start;

  uiNH = stpDosH->e_lfanew;
  printf("IMAGE_HEADER->e_lfanew      [%08X]\n", uiNH);

  stPNtH = (IMAGE_NT_HEADERS32 *)( ( (int)vpMem_start) + uiNH );
  printf("IMAGE_NT_HEADERS32       [%08X]\n", stPNtH);

  stpFH = (IMAGE_FILE_HEADER * )( (int)stPNtH + sizeof(stPNtH->Signature) );
  printf("IMAGE_NT_HEADERS32->IMAGE FILE HEADER  [%08X]\n", stpFH);

  uiSizeofOH = stpFH->SizeOfOptionalHeader;
  printf("Size of Optional Header     [%08X]\n", uiSizeofOH);

  uiOHaddr = (unsigned int) ( &(stPNtH->OptionalHeader) );
  printf("addr. of OH         [%08X]\n", uiOHaddr);

  stpSHt = (IMAGE_SECTION_HEADER*) ((int)uiOHaddr + uiSizeofOH);
  printf("addr. of SH. txt       [%08X]\n", stpSHt);

  uiPRDt = stpSHt->PointerToRawData;
  uiSRDt = stpSHt->SizeOfRawData;
  uiPRDd = uiSRDt + uiPRDt;
  
  printf("size of raw data. txt       [%08X]\n", uiSRDt);
  printf("pointer to raw data. txt    [%08X]\n", uiPRDt);
  printf("pointer to raw data. data     [%08X]\n", uiPRDd);  
  printf("------------------ LOAD PROCEDURE ------------------\n");  

  iRtn = lseek(iFd, uiPRDt, SEEK_SET);
  if(0 > iRtn)
  {
    memory_clear();
    close(iFd);
    printf("프로그램 적재 실패\n");
    return;
  }

  iRtn = read(iFd, vpCode, SECTION_SIZE);
  if(0 > iRtn)
  {
    memory_clear();
    close(iFd);
    printf("프로그램 적재 실패\n");
    return;
  }
  printf("코드영역 적재 완료\n");

  iRtn = lseek(iFd, uiPRDd, SEEK_SET);
  if(0 > iRtn)
  {
    memory_clear();
    close(iFd);
    printf("프로그램 적재 실패\n");
    return;
  }

  iRtn = read(iFd, vpData, SECTION_SIZE);
  if(0 > iRtn)
  {
    memory_clear();
    close(iFd);
    printf("프로그램 적재 실패\n");
    return;
  }
  else if(0 == iRtn)
  {
    memory_clear();
    close(iFd);
    printf("데이터 영역이 존재하지 않습니다.\n");  
    return;
  }    
  printf("데이터영역 적재 완료\n");    
  
  return;
}


반응형
Posted by newind2000
Busan IT/Assembly2015. 10. 22. 08:45

==================================Outline====================================

PE구조체

----------------------------------------------------------------------------

load함수를 구현해보자.

 

프로그램을 메모리에 입력시키기 위해서는 실행 파일이 메모리에 어떻게 적재 되는지 알아야 한다.




 

lseek을 사용하여 “.text"가 있는 곳까지 이동시켜야 한다.

 

도스헤더의 주소를 받은 후 '1D8'만큼 떨어진 Section header(".text")에서 Section(".text")의 주소를 찾아야 한다.

 

http://haerakai.tistory.com/18

 

위에 블로그에 접속하여 정독한다.

 

 

 

 

 

 

 

 

반응형
Posted by newind2000
Busan IT/Assembly2015. 10. 20. 17:34

==================================Outline====================================

memory_modify함수

----------------------------------------------------------------------------

메모리의 값을 수정해주는 함수를 만들자.

 

함수의 이름은 'memory_modify'이다. 이 함수는 원하는 메모리 주소에 찾아가서 1byte의 값을 바꾸는 역할을 한다.

 

void memory_modify()
{
  unsigned int uiAddr;
  unsigned int uiVal;  
  while(1)
  {
    printf("수정할 메모리 주소를 입력하세요 [%08X - %08X]  :  ", vpMem_start, vpMem_end);
    scanf("%x"&uiAddr);
    fflush(0);
    if(uiAddr < (unsigned int)vpMem_start || uiAddr > (unsigned int)vpMem_end)
    {
      printf("잘못입력하셨습니다. \n");
      continue;
    }
    break;    
  }
  hexaview((void *)uiAddr, 16);
  printf("수정할 값을 입력하세요 : ");
  scanf("%x"&uiVal);  
  
  fflush(0);  

  *((unsigned int *)uiAddr) = uiVal;
  hexaview((void *)uiAddr, 16);  
  return;
}

 

내일은 load함수를 하겠다.


 /*** 코드 ***/

#include <stdio.h>

/*  사용자 정의  */
#define CMD_SIZE   20
#define  MAX_PRG_SIZE  (64*1024)
#define  MEM_SIZE   (MAX_PRG_SIZE*2)
#define  MASK_CODE  0xFFFF0000
typedef struct
{
  unsigned int efl;
  unsigned int eip;
  unsigned int edi;
  unsigned int esi;
  unsigned int ebp;
  unsigned int esp;
  unsigned int ebx;
  unsigned int edx;
  unsigned int ecx;
  unsigned int eax;
  
}context;

typedef struct
{
  char * cpCmd;
  void (*fp)();  
}comm;

/*   전역 변수  */
static context stOld_state;
extern void stst(context *);
extern void ldst(context *);
void * vpMem_start;
void * vpMem_end;
void print_addr();
void * vpCode;
void * vpData;
void * vpStack;

/*  함수 원형  */
void print_r();
void print_help();
void memory_clear();
void quit();
void view_code();
void view_data();
void view_stack();
void load();
void memory_modify();


void hexaview(void *, unsigned int);

comm stCmd_Map[] ={  //메세지 맵 기법
         {
        "R", print_r
         },
      {
        "H", print_help
      },
      {  
        "MC", memory_clear      
      },
      {  
        "Q", quit
      },
      {
        "QUIT", quit 
      },
      {
        "P", print_addr
      },        
      {
        "CODE", view_code
      },
      {
        "DATA", view_data
      },
      {
        "STACK", view_stack
      },
      {
        "LOAD", load
      },
      {
        "MM", memory_modify
      },
         {
        00
         }        
      };
int main(void)
{
  char cInput[CMD_SIZE];
  comm * stpCmd;
  int iRet;  
  
  vpMem_start = (void *)malloc(MEM_SIZE);
  if(0==vpMem_start)
  {
    return -1;
  }
  vpCode = (void *)( ( ((int)vpMem_start) & (MASK_CODE) )+MAX_PRG_SIZE);
  vpData = (void *)((int)vpCode + 0x2000);   
  vpMem_end = (void *)( (int)vpMem_start + MEM_SIZE - 1 );    
  vpStack = (void *)( (int)vpMem_end - (16 * 16)+1);
  
  stst(&stOld_state);  
  printf("Moniter Program Start\n");
  while(1)
  {
    putchar('>');    
    iRet = read(0, cInput, CMD_SIZE);
    if(iRet < 2)
    {
      continue;  
    }    
    cInput[iRet-1= 0;    
    strupr(cInput);
    
    stpCmd = stCmd_Map;
    while(0 != (stpCmd->fp))
    {
      if(0 == strcmp(strupr(cInput), stpCmd->cpCmd))
      {
        break;
      }      
      ++stpCmd;
    }
    if(0!= (stpCmd->fp))
    {
      ((stpCmd->fp)());      
      
    }
    else
    {
      print_help();
    }    
  }
  return 0;
}
void print_r()
{
  printf("main    : %08X\n", main);
  printf("stOld_state  : %08X\n\n"&stOld_state);
  printf("EAX = %08X  EBX = %08X\nECX = %08X  EDX = %08X\nESI = %08X  EDI = %08X\nEBP = %08X  ESP = %08X\nEIP = %08X  EFL = %08X\n\n",stOld_state.eax, stOld_state.ebx, stOld_state.ecx, stOld_state.edx, stOld_state.esi, stOld_state.edi, stOld_state.ebp, stOld_state.esp, stOld_state.eip, stOld_state.efl);

}
void print_help()
{
  printf("Memory Debugging Prompt\n\n");
  printf("R: Print Register Info.\n");
  printf("H: Print Command List\n");    
  printf("H: Clear Momory\n");    
  printf("P: Print Memory\n");
}
void memory_clear()
{  
  memset(vpMem_start, 0, MEM_SIZE);  
}
void print_addr()
{
  printf("Code Start Address    : 0x%08X\n", vpCode);  
  printf("Dynamic Memory Area    : 0x%08X - 0x%08X [128Byte]\n", vpMem_start, vpMem_end);
}
void quit()
{
  free(vpMem_start);
  exit(0);
}
void view_code()
{
  hexaview(vpCode, 16*16);

  return;
}

void view_data()
{
  hexaview(vpData, 16*16);

  return;
}
void view_stack()
{
  hexaview(vpStack, 16*16);

  return;
}
void load()
{
  memset(vpCode, 0xFF, 16*16);
  memset(vpData, 0xEE, 16*16);
  memset(vpStack, 0xDD, 16*16);

  return;
}
void memory_modify()
{
  unsigned int uiAddr;
  unsigned int uiVal;  
  while(1)
  {
    printf("수정할 메모리 주소를 입력하세요 [%08X - %08X]  :  ", vpMem_start, vpMem_end);
    scanf("%x"&uiAddr);
    fflush(0);
    if(uiAddr < (unsigned int)vpMem_start || uiAddr > (unsigned int)vpMem_end)
    {
      printf("잘못입력하셨습니다. \n");
      continue;
    }
    break;    
  }
  hexaview((void *)uiAddr, 16);
  printf("수정할 값을 입력하세요 : ");
  scanf("%x"&uiVal);  
  
  fflush(0);  

  *((unsigned int *)uiAddr) = uiVal;
  hexaview((void *)uiAddr, 16);  
  return;
}


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)
  {
    printf(" %08X  ", vP);
  
    for(uiCnt=0; uiCnt<16; ++uiCnt)
    {
      printf("%02X ", *((unsigned char *)vP));
      vP = (char *)vP + 1;
    }
    vP = (char *)vP - 16;
    putchar(' ');

    for(uiCnt=0; uiCnt<16; ++uiCnt)
    {
      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');
  }
  return;
}


 

반응형

'Busan IT > Assembly' 카테고리의 다른 글

LOAD함수 구현  (0) 2015.10.23
PE구조체  (0) 2015.10.22
코드/데이터/스택 영역 설정, load, clear  (0) 2015.10.20
메모리 출력 프로그램 #1  (0) 2015.10.15
stst(store state), ldst(load state)  (0) 2015.10.15
Posted by newind2000
Busan IT/Assembly2015. 10. 20. 09:35

==================================Outline====================================

코드/데이터/스택 영역 설정

load, clear

----------------------------------------------------------------------------

 

코드/데이터/스택 영역 설정

 

동적 할당을 받은 영역에 코드영역, 데이터영역, 스택영역을 설정 해주자.

 

코드 영역은 헥사 값으로 뒤의 4자리가 ‘0’으로 채워져 있어야 한다. 이를 위한 마스크 설정을 해주자.

 

#define MASK_CODE 0xFFFF0000

#define MAX_PRG_SIZE (64*1024)

#define MEM_SIZE (MAX_PRG_SIZE*2)

 

vpCode = (void *)( ( ((int)vpMem_start) & (MASK_CODE) )+MAX_PRG_SIZE);

 

프로그램 사이즈를 더해준 이유는 마스크 코드를 적용할 시 뒤에 4자리가 삭제되기 때문이다.

뒤에 네 자리는 0xFFFF - 0x0000까지 가능한데 이 값을 복구시켜주기 위해 프로그램 사이즈를 더해준다. 처음에 동적할당을 받을 때 'MEM_SIZE' , 프로그램 사이즈의 2배임으로 동적할당을 받은 영역 내에서 프로그램이 존재하게 된다.

 

데이터영역은 코드영역에서 헥사 값으로 2000떨어진 곳에 존재한다.

 

vpData = (void *)((int)vpCode + 0x2000);

 

스택 값은 끝에서부터 시작된다. 이것을 헥사뷰로 16줄을 출력시키기 위해 다음과 같은 코딩을 한다.

 

vpStack = (void *)( (int)vpMem_end - (16 * 16)+1);

 

load, clear

 

각 영역이 올바른 주소 값으로 설정되어 있는지 출력해본다. 올바르게 나온다면 각 영역에 값을 저장할 'load'명령어와 해당 영역을 ‘0’으로 채워주는 'mc'(memory clear) 함수를 만들어준다.

 

void load()

{

memset(vpCode, 0xFF, 16*16);

memset(vpData, 0xEE, 16*16);

memset(vpStack, 0xDD, 16*16);

 

return;

}

 

void memory_clear()

{

memset(vpMem_start, 0, MEM_SIZE);

}




/*** Code ***/

#include <stdio.h>

/*  사용자 정의  */
#define CMD_SIZE   20
#define  MAX_PRG_SIZE  (64*1024)
#define  MEM_SIZE   (MAX_PRG_SIZE*2)
#define  MASK_CODE  0xFFFF0000
typedef struct
{
  unsigned int efl;
  unsigned int eip;
  unsigned int edi;
  unsigned int esi;
  unsigned int ebp;
  unsigned int esp;
  unsigned int ebx;
  unsigned int edx;
  unsigned int ecx;
  unsigned int eax;
  
}context;

typedef struct
{
  char * cpCmd;
  void (*fp)();  
}comm;

/*   전역 변수  */
static context stOld_state;
extern void stst(context *);
extern void ldst(context *);
void * vpMem_start;
void * vpMem_end;
void print_addr();
void * vpCode;
void * vpData;
void * vpStack;

/*  함수 원형  */
void print_r();
void print_help();
void memory_clear();
void quit();
void view_code();
void view_data();
void view_stack();
void load();


void hexaview(void *, unsigned int);

comm stCmd_Map[] ={  //메세지 맵 기법
         {
        "R", print_r
         },
      {
        "H", print_help
      },
      {  
        "MC", memory_clear      
      },
      {  
        "Q", quit
      },
      {
        "QUIT", quit 
      },
      {
        "P", print_addr
      },        
      {
        "CODE", view_code
      },
      {
        "DATA", view_data
      },
      {
        "STACK", view_stack
      },
      {
        "LOAD", load
      },
         {
        00
         }        
      };
int main(void)
{
  char cInput[CMD_SIZE];
  comm * stpCmd;
  int iRet;  
  
  vpMem_start = (void *)malloc(MEM_SIZE);
  if(0==vpMem_start)
  {
    return -1;
  }
  vpCode = (void *)( ( ((int)vpMem_start) & (MASK_CODE) )+MAX_PRG_SIZE);
  vpData = (void *)((int)vpCode + 0x2000);   
  vpMem_end = (void *)( (int)vpMem_start + MEM_SIZE - 1 );    
  vpStack = (void *)( (int)vpMem_end - (16 * 16)+1);
  
  stst(&stOld_state);  
  printf("Moniter Program Start\n");
  while(1)
  {
    putchar('>');    
    iRet = read(0, cInput, CMD_SIZE);
    if(iRet < 2)
    {
      continue;  
    }    
    cInput[iRet-1= 0;    
    strupr(cInput);
    
    stpCmd = stCmd_Map;
    while(0 != (stpCmd->fp))
    {
      if(0 == strcmp(strupr(cInput), stpCmd->cpCmd))
      {
        break;
      }      
      ++stpCmd;
    }
    if(0!= (stpCmd->fp))
    {
      ((stpCmd->fp)());      
      
    }
    else
    {
      print_help();
    }    
  }
  return 0;
}
void print_r()
{
  printf("main    : %08X\n", main);
  printf("stOld_state  : %08X\n\n"&stOld_state);
  printf("EAX = %08X  EBX = %08X\nECX = %08X  EDX = %08X\nESI = %08X  EDI = %08X\nEBP = %08X  ESP = %08X\nEIP = %08X  EFL = %08X\n\n",stOld_state.eax, stOld_state.ebx, stOld_state.ecx, stOld_state.edx, stOld_state.esi, stOld_state.edi, stOld_state.ebp, stOld_state.esp, stOld_state.eip, stOld_state.efl);

}
void print_help()
{
  printf("Memory Debugging Prompt\n\n");
  printf("R: Print Register Info.\n");
  printf("H: Print Command List\n");    
  printf("H: Clear Momory\n");    
  printf("P: Print Memory\n");
}
void memory_clear()
{  
  memset(vpMem_start, 0, MEM_SIZE);  
}
void print_addr()
{
  printf("Code Start Address    : 0x%08X\n", vpCode);  
  printf("Dynamic Memory Area    : 0x%08X - 0x%08X [128Byte]\n", vpMem_end, vpMem_start);
}
void quit()
{
  free(vpMem_start);
  exit(0);
}
void view_code()
{
  hexaview(vpCode, 16*16);

  return;
}

void view_data()
{
  hexaview(vpData, 16*16);

  return;
}
void view_stack()
{
  hexaview(vpStack, 16*16);

  return;
}
void load()
{
  memset(vpCode, 0xFF, 16*16);
  memset(vpData, 0xEE, 16*16);
  memset(vpStack, 0xDD, 16*16);

  return;
}


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)
  {
    printf(" %08X  ", vP);
  
    for(uiCnt=0; uiCnt<16; ++uiCnt)
    {
      printf("%02X ", *((unsigned char *)vP));
      vP = (char *)vP + 1;
    }
    vP = (char *)vP - 16;
    putchar(' ');

    for(uiCnt=0; uiCnt<16; ++uiCnt)
    {
      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');
  }
  return;
}


 

 

 

 

반응형
Posted by newind2000