검색결과 리스트
부산IT학원/스마트컨트롤러에 해당되는 글 131건
- 2014.08.26 20140826 (작성 중인 프로그램)
- 2014.08.25 20140825 (다른 프로그램 실행 분석 프로그램 작성)
- 2014.08.22 20140822 (다른 프로그램 실행 분석 프로그램 작성)
- 2014.08.20 20140820 (PE 구조)
- 2014.08.18 20140818 (Assembly CDECL, STDCALL, PE구조)
- 2014.08.05 20140805 (Assembly 함수 return 값, 인수)
- 2014.08.04 20140804 (Assembly procedure(함수 구현), call, ret, 지역변수, Entry Code, Exit Code)
- 2014.08.01 20140801 (Assembly push, pop, pushad, popad, pushfd, popfd)
- 2014.07.31 20140731 (Assembly loop, 배열, lea, pipe line)
- 2014.07.30 20140730 (rounding factor, adc, sbb, clc, stc, cmc, jmp, cmp)
글
20140826 (작성 중인 프로그램)
127일차
---------------------
작성 중인 프로그램
---------------------
------- 현재 작성 중인 프로그램은 windows loader 같은 프로그램이다.
새로운 프로그램을 불러 올 때마다 heap을 할당 받고,
할당 받은 stack에 ESP를 위치하게 한다.
data 영역은 0x2000 만큼 떨어져 있다고 한다.
그래서 우리가 받은 자료 t1.exe를 link 한 프로그램으로 돌리면 뻑이 났다.
link /subsystem:console /entry:init /nodefaultlib /out:t1.exe /base:0x520000 init.obj monitor.obj t1.obj
이래 고치면 뻑이 안난다.
->link /subsystem:console /entry:init /nodefaultlib /out:t1.exe /base:0x430000 init.obj monitor.obj t1.obj
추가한 함수
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140924 (비트맵 파일 구조) (0) | 2014.09.25 |
---|---|
20140827 (메시지 맵, strrev, strupr, toupper, strlwr, tolower, strchr, strstr, strtol, strtoul, strod) (0) | 2014.08.27 |
20140825 (다른 프로그램 실행 분석 프로그램 작성) (0) | 2014.08.25 |
20140822 (다른 프로그램 실행 분석 프로그램 작성) (0) | 2014.08.22 |
20140820 (PE 구조) (0) | 2014.08.20 |
글
20140825 (다른 프로그램 실행 분석 프로그램 작성)
126일차
---------------------------
현재 작성 중인 프로그램
---------------------------
------- 진행 상황
"현재" 처럼 프로그램을 구현하였는데
"수정" 으로 프로그램을 구현할 것이다.
------- 추가된 소스
--- 설명을 위해 임시로 추가한 소스 실행 전 상태이다.
--- LDST(&temp) 호출
EIP가 code 주소를 가리키게 되면서 main 에서 불러온 t1.exe 를 실행하게 된다.
--- t1.exe 에 inti.asm 코드
LDST(&status)가 호출되면서 STST()가 실행된 지점으로 돌아간다.
------- bzero
리눅스에서 사용가능 함수
#include <string.h>
void bzero(void * s , size_t n);
바이트 스트링 s 의 처음 n 바이트를 0으로 채운다. memset(3)과 마찬가지로 메모리를 초기화하기 위한 목적으로 주로 사용된다. 그러나 이 함수는 구식이 되으므로 bzero 대신 memset(3) 을 사용하도록 한다.
반환값 없음.
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140827 (메시지 맵, strrev, strupr, toupper, strlwr, tolower, strchr, strstr, strtol, strtoul, strod) (0) | 2014.08.27 |
---|---|
20140826 (작성 중인 프로그램) (0) | 2014.08.26 |
20140822 (다른 프로그램 실행 분석 프로그램 작성) (0) | 2014.08.22 |
20140820 (PE 구조) (0) | 2014.08.20 |
20140818 (Assembly CDECL, STDCALL, PE구조) (0) | 2014.08.18 |
글
20140822 (다른 프로그램 실행 분석 프로그램 작성)
125일차
------------------------------
실행 파일 분석 프로그램 작성
------------------------------
소스
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <windows.h>
#define MAX_PROGRAM_SIZE 0x10000
typedef struct _context
{
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;
static unsigned char * Mem; // 동적 메모리 시작 주소
static unsigned char * Mem_End; // 동적 메모리 끝 주소
static unsigned char * code; // 프로그램 저장공간의 시작 위치 - Code
int File_DS; // 저수준 파일의 데스크립터
extern void STST(Context *); // Reg 상태 저장
extern void LDST(Context *);
extern void MM(void *, unsigned char);// Memory 수정
extern unsigned char MD(void *); // Memory 보기
void load();
void HexaView(void *);
void Print_Register(Context *);
void Memory_Clear();
int main()
{
Context status;
unsigned int uiNum;
Mem = malloc(MAX_PROGRAM_SIZE*2);
if(0 == Mem)
{
printf("동적 할당을 받을 수 없습니다.\n");
printf("프로그램을 종료합니다.\n");
return 0;
}
else
{
code = (unsigned char *)(((unsigned int)Mem + MAX_PROGRAM_SIZE) & 0xFFFF0000);
Mem_End = Mem + MAX_PROGRAM_SIZE*2 - 1;
printf("Dynamic Memory area\t: 0x%08X to 0x%08X (128KBytes)\n", Mem, Mem_End);
}
printf("Code Start Address\t: 0x%08X\n", code);
STST(&status);
Print_Register(&status);
load();
HexaView(code);
printf("1: 프로그램 재시작, 2 : 프로그램 종료\n");
printf("선택하세요 : ");
scanf("%d", &uiNum);
if(uiNum == 1)
{
LDST(&status);
}
free(Mem);
return 0;
}
void load()
{
int Read_Num;
int Header_Size;
unsigned int uiSection_Size;
IMAGE_DOS_HEADER * stpDH;
IMAGE_NT_HEADERS * stpPH;
IMAGE_FILE_HEADER * stpFH;
IMAGE_OPTIONAL_HEADER32 * stpOH;
File_DS = open("t1.exe", O_RDONLY);
if(File_DS < 0)
{
printf("파일 열기 실패.\n");
return;
}
Read_Num = read(File_DS, Mem, MAX_PROGRAM_SIZE*2);
if(0 >= Read_Num)
{
printf("파일 읽기 실패(1).\n");
close(File_DS);
return;
}
stpDH = (IMAGE_DOS_HEADER *)Mem;
stpPH = (IMAGE_NT_HEADERS *)(Mem + stpDH->e_lfanew-1);
stpFH = (IMAGE_FILE_HEADER *)( ((char *)(stpPH)) + 4 );
stpOH = (IMAGE_OPTIONAL_HEADER32 *)( ((char *)(stpFH)) + sizeof(IMAGE_FILE_HEADER));
Header_Size = stpOH->SizeOfHeaders; // Header size
uiSection_Size = stpOH->FileAlignment; // Section size
Memory_Clear(); // Memory clear
lseek(File_DS, Header_Size, SEEK_SET); // 파일 포인터 위치 이동
Read_Num = read(File_DS, code, uiSection_Size);
if(0 >= Read_Num)
{
printf("파일 읽기 실패(2).\n");
close(File_DS);
return;
}
close(File_DS);
}
void HexaView(void * vpData)
{
int iCnt;
int iCnt2;
printf("===============================================================================\n");
printf("= ADDRESS HEXA ASCII =\n");
printf("=-----------------------------------------------------------------------------=\n");
for(iCnt2=0; 20>iCnt2; ++iCnt2)
{
//--- Address Part Start
printf("= %08X ", vpData );
//--- Address Part End
//--- Hexa View Part Start
for(iCnt=0; 16>iCnt; ++iCnt)
{
if(7 == iCnt)
{
printf("%02X ", (*((unsigned char *)vpData)) );
}
else
{
printf("%02X ", (*((unsigned char *)vpData)) );
}
++((unsigned char *)vpData);
}
//--- Hexa View Part End
//--- ASCII Part Start
((unsigned char *)vpData) = ((unsigned char *)vpData) - iCnt;
for(iCnt=0; 16>iCnt; ++iCnt)
{
if(0x20 <= (*((unsigned char *)vpData)) && 0x80 > (*((unsigned char *)vpData)))
{
printf("%c", (*((unsigned char *)vpData)));
}
else
{
printf(".");
}
++((unsigned char *)vpData);
}
printf(" =\n");
//--- ASCII Part End
}
printf("===============================================================================\n");
return ;
}
void Print_Register(Context * status)
{
printf("EAX : %08X \n", status->EAX);
printf("ECX : %08X \n", status->ECX);
printf("EDX : %08X \n", status->EDX);
printf("EBX : %08X \n", status->EBX);
printf("ESP : %08X \n", status->ESP);
printf("EBP : %08X \n", status->EBP);
printf("ESI : %08X \n", status->ESI);
printf("EDI : %08X \n", status->EDI);
printf("EIP : %08X \n", status->EIP);
printf("EFL : %08X \n\n", status->EFL);
}
void Memory_Clear()
{
unsigned char * ucData;
ucData = Mem;
while(1)
{
MM(ucData, 0x00);
++ucData;
if(ucData > Mem_End)
{
break;
}
}
}
외부 함수 Asm 코드
.386
.MODEL FLAT
.STACK 4096
PUBLIC _LDST
PUBLIC _STST
PUBLIC _MM
PUBLIC _MD
.CODE
_LDST PROC NEAR32 ; LoaD STatus Procedure Start
push ebp ; Entry Code
mov ebp, esp ; Entry Code
add esp, 12 ; load EFL
popfd
pop eax ; load EIP
mov [esp-16], eax
popad ; load Reg
mov esp, ebp ; Exit Code
pop ebp ; Exit Code
ret ; Exit Code
_LDST EndP ; LoaD STatus Procedure End
_STST PROC NEAR32
push ebp ; Entry Code
mov ebp, esp ; Entry Code
pushfd ; save temp EFL
add esp, 56
pushad ; save Reg
mov eax, [ebp+4] ; save EIP
push eax
mov eax, [ebp-4] ; save EFL
push eax
mov esp, ebp ; Exit Code
pop ebp ; Exit Code
ret ; Exit Code
_STST ENDP
_MM PROC NEAR32 ; Memory Modify
push ebp ; Entry Code
mov ebp, esp ; Entry Code
mov al, [ebp+12]
mov esp, [ebp+8]
mov [esp], al
mov esp, ebp ; Exit Code
pop ebp ; Exit Code
ret ; Exit Code
_MM EndP ; Memory Modify
_MD PROC NEAR32 ; Memory Display
push ebp ; Entry Code
mov ebp, esp ; Entry Code
mov esp, [ebp+8]
mov al, [esp]
mov esp, ebp ; Exit Code
pop ebp ; Exit Code
ret ; Exit Code
_MD EndP ; Memory Display
END
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140826 (작성 중인 프로그램) (0) | 2014.08.26 |
---|---|
20140825 (다른 프로그램 실행 분석 프로그램 작성) (0) | 2014.08.25 |
20140820 (PE 구조) (0) | 2014.08.20 |
20140818 (Assembly CDECL, STDCALL, PE구조) (0) | 2014.08.18 |
20140805 (Assembly 함수 return 값, 인수) (0) | 2014.08.05 |
글
20140820 (PE 구조)
123일차
--------------
PE 구조
--------------
--- Dos Header
Dos와 호환용으로 있는 부분으로
항상 64 byte 크기이며 안에 여러 구조체 멤버가 있는데,
e_magic, e_lfanew 이 두 멤버가 가장 중요하고 나머지는 0으로 채워도 돌아간다.
magic은 항상 아스키값으로 MZ를 나타내야 하고,
e_lfanew 는 PE 헤더의 시작 점을 나타내고 있다.
--- Dos stub
가변적인 크기로 dos 모드에서 실행되는 것을 방지하기 위한 곳이라고 한다.
가끔 바이러스 코드를 이 곳에 넣기도 한다고 한다.
--- 각 구조체
typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER OptionalHeader; } IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
Signature 의 값은 항상 50 45 00 00 값으로 PE구조라고 부른다.
typedef struct _IMAGE_FILE_HEADER {
WORD Machine;
WORD NumberOfSections;
DWORD TimeDateStamp;
DWORD PointerToSymbolTable;
DWORD NumberOfSymbols;
WORD SizeOfOptionalHeader;
WORD Characteristics;
} IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
typedef struct _IMAGE_FILE_HEADER { WORD Machine; WORD NumberOfSections; DWORD TimeDateStamp; DWORD PointerToSymbolTable; DWORD NumberOfSymbols; WORD SizeOfOptionalHeader; WORD Characteristics; } IMAGE_FILE_HEADER, *PIMAGE_FILE_HEADER;
Machine 은 이 파일이 실행 가능한 cpu의 타입 정보를 갖고 있다.
typedef struct _IMAGE_OPTIONAL_HEADER {
WORD Magic;
BYTE MajorLinkerVersion;
BYTE MinorLinkerVersion;
DWORD SizeOfCode;
DWORD SizeOfInitializedData;
DWORD SizeOfUninitializedData;
DWORD AddressOfEntryPoint;
DWORD BaseOfCode;
DWORD BaseOfData;
DWORD ImageBase;
DWORD SectionAlignment;
DWORD FileAlignment;
WORD MajorOperatingSystemVersion;
WORD MinorOperatingSystemVersion;
WORD MajorImageVersion;
WORD MinorImageVersion;
WORD MajorSubsystemVersion;
WORD MinorSubsystemVersion;
DWORD Win32VersionValue;
DWORD SizeOfImage;
DWORD SizeOfHeaders;
DWORD CheckSum;
WORD Subsystem;
WORD DllCharacteristics;
DWORD SizeOfStackReserve;
DWORD SizeOfStackCommit;
DWORD SizeOfHeapReserve;
DWORD SizeOfHeapCommit;
DWORD LoaderFlags;
DWORD NumberOfRvaAndSizes;
IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
} IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
typedef struct _IMAGE_OPTIONAL_HEADER { WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; DWORD ImageBase; DWORD SectionAlignment; DWORD FileAlignment; WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER, *PIMAGE_OPTIONAL_HEADER;
typedef struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680305(v=vs.85).aspx
typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; } Misc; DWORD VirtualAddress; DWORD SizeOfRawData; DWORD PointerToRawData; DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;
http://msdn.microsoft.com/en-us/library/windows/desktop/ms680341(v=vs.85).aspx
--- PEViewer 프로그램
--- 실습
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140825 (다른 프로그램 실행 분석 프로그램 작성) (0) | 2014.08.25 |
---|---|
20140822 (다른 프로그램 실행 분석 프로그램 작성) (0) | 2014.08.22 |
20140818 (Assembly CDECL, STDCALL, PE구조) (0) | 2014.08.18 |
20140805 (Assembly 함수 return 값, 인수) (0) | 2014.08.05 |
20140804 (Assembly procedure(함수 구현), call, ret, 지역변수, Entry Code, Exit Code) (0) | 2014.08.04 |
글
20140818 (Assembly CDECL, STDCALL, PE구조)
121일차
---------------
Assembly
---------------
------- CDECL & STDCALL 방식
CDECL , STDCALL 방식은 함수 호출 후 인수를 정리하는 방식으로
호출한 곳에서 인수를 정리하면 CDECL 방식,
호출당한 곳에서 인수를 정리하면 STDCALL 방식이다.
--- CDECL 방식 예제코드
aaa() 함수를 호출한 main() 함수에서 add esp , 8 로 인수를 정리하고 있다.
--- STDCALL 방식 예제코드
호출당한 aaa() 함수에서 마지막에 ret 8 로 인수를 정리하고 있다.
위의 소스에서 확인할 수 있듯이 __stdcall을 붙이면 STDCALL 방식으로 되고
생략 시 CDECL 방식으로 작성된다.
STDCALL 방식이 1byte 더 아낄 수 있다고 하는데...
얼마 전에 배운 ARM 같은 경우, 인수 4개까지 Reg에 저장한다고 한다.
적절히 사용할 경우 더 효율적으로 사용할 수 있다.
------- STST 함수와 LDST 함수
STST() 함수는 Register들을 저장하는 것이고,
LDST() 함수는 STST() 함수를 저장할 당시 Register 들의 상태로 되돌리고
STST() 이후로 돌아가는 함수이다.
--------------
PE 구조
--------------
PE(Portable Executable)파일은 말 그대로 옮겨다니면서 실행시킬수 있는 파일을 말합니다.
실행 계열 : EXE, SCR | 드라이버 계열 : SYS, VXD |
라이브러리 계열 : DLL, OCX, CPL, DRV | 오브젝트 파일 계열 : OBJ |
typedef struct _IMAGE_DOS_HEADER {WORD e_magic; // DOS signature : 4D5A ("MZ")
WORD e_cblp;
WORD e_cp;
WORD e_crlc;
WORD e_cparhdr;
WORD e_minalloc;
WORD e_maxalloc;
WORD e_ss;
WORD e_sp;
WORD e_csum;
WORD e_ip;
WORD e_cs;
WORD e_lfarlc;
WORD e_ovno;
WORD e_res[4];
WORD e_oemid;
WORD e_oeminfo;
WORD e_res2[10];
LONG e_lfanew; // offset to NT header
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
여기서 중요한 값은 e_magic, e_lfanew 이렇게 2개가 있습니다.
여기서 e_magic의 값은 DOS signature로 MZ라는 문자열입니다.
(MZ는 Mark Zbikowski라고 DOS실행파일을 설계한 사람의 이니셜입니다.)
또한 e_lfanew의 값은 NT header의 RVA형태의 주소값을 가지고있습니다.
(이 값은 꼭 40이상의 크기를 가질 필요는 없습니다.)
_IMAGE_DOS_HEADER 확인 예제 코드)
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#define READ_EXE_FILE_SIZE 256
int main()
{
IMAGE_DOS_HEADER * stpExe;
unsigned char ucBuff[READ_EXE_FILE_SIZE];
int iFile;
iFile = open("print_test.bin", O_RDONLY);
if(0 > iFile)
{
fprintf(stderr, "File open error!\n");
return 0;
}
read(iFile, &ucBuff, READ_EXE_FILE_SIZE);
stpExe = (IMAGE_DOS_HEADER *)ucBuff;
printf("e_magic\t\t\t\t: [ %c%c ]\n", ucBuff[0], ucBuff[1]);
printf("bytes on last page of file\t: [ %d ]\n", stpExe->e_cblp);
printf("Pages in file\t\t\t: [ %d ]\n", stpExe->e_cp);
printf("Relocations\t\t\t: [ %d ]\n", stpExe->e_crlc);
printf("Size of header in paragraphs\t: [ %d ]\n", stpExe->e_cparhdr);
printf("Minimum extra paragraphs needed\t: [ %d ]\n", stpExe->e_minalloc);
printf("Maximum extra paragraphs needed\t: [ %d ]\n", stpExe->e_maxalloc);
printf("Initial (relative) SS value\t: [ %d ]\n", stpExe->e_ss);
printf("Initial SP value\t\t: [ %d ]\n", stpExe->e_sp);
printf("Checksum\t\t\t: [ %d ]\n", stpExe->e_csum);
printf("Initial IP value\t\t: [ %d ]\n", stpExe->e_ip);
printf("Initial (relative) CS value\t: [ %d ]\n", stpExe->e_cs);
printf("File address of relocation table : [ %d ]\n", stpExe->e_lfarlc);
printf("Overlay number\t\t\t: [ %d ]\n", stpExe->e_ovno);
printf("Reserved words\t\t\t: [ %d ]\n", stpExe->e_res[4]);
printf("OEM identifier (for e_oeminfo)\t: [ %d ]\n", stpExe->e_oemid);
printf("OEM information; e_oemid specific : [ %d ]\n", stpExe->e_oeminfo);
printf("Reserved words\t\t\t: [ %d ]\n", stpExe->e_res2[10]);
printf("File address of new exe header\t: [ %d ]\n", stpExe->e_lfanew);
return 0;
}
실행 결과
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140822 (다른 프로그램 실행 분석 프로그램 작성) (0) | 2014.08.22 |
---|---|
20140820 (PE 구조) (0) | 2014.08.20 |
20140805 (Assembly 함수 return 값, 인수) (0) | 2014.08.05 |
20140804 (Assembly procedure(함수 구현), call, ret, 지역변수, Entry Code, Exit Code) (0) | 2014.08.04 |
20140801 (Assembly push, pop, pushad, popad, pushfd, popfd) (0) | 2014.08.01 |
글
20140805 (Assembly 함수 return 값, 인수)
117일차
---------------
Assembly
---------------
------- Procedure
--- return 비교
--- 지역 변수 선언
중복이 되므로 중복을 최대한 피해야 최적화 할 수 있다.
ESP가 88 byte만큼 움직인다. 즉, 88 byte 만큼 확보.
그런데 이상한게 int a, a0 ~ a9 까지 11개 44 byte.
int b[10] 은 40 byte 합 84 byte가 나와야 하는데 88 byte 이다.
확인한 결과 [2] -> [3]으로 바뀔 때 4 byte를 더 할당 받는다.
이유는 모르겠다.
--- 함수 호출시 인수 값을 바꾸는 asm 코드 예제 1)
iNum이란 초기화 되지 않은 변수를
smart 함수에 인수로 넣으면
초기화 시켜주는 소스.
- C 소스
- C 소스에서 호출할 asm 함수.
mov eax , [ebp+8] 이 코드는
eax 가 &iNum을 가리키기 하기 위해 ebp+8을 하였다.
아래 그림을 참고.
--- 함수 호출시 인수 값을 바꾸는 asm 코드 예제 2)
현재 EAX, EBX, ECX, EDX를 출력하는 소스
- C 소스
- C 소스에서 호출할 asm 함수.
mov eax , [ebp-4]
이 코드는
mov mem , mem 이런 mov operand가 없기 때문에
mov mem , reg 로 넣기 위해서 이다.
--- ???
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140820 (PE 구조) (0) | 2014.08.20 |
---|---|
20140818 (Assembly CDECL, STDCALL, PE구조) (0) | 2014.08.18 |
20140804 (Assembly procedure(함수 구현), call, ret, 지역변수, Entry Code, Exit Code) (0) | 2014.08.04 |
20140801 (Assembly push, pop, pushad, popad, pushfd, popfd) (0) | 2014.08.01 |
20140731 (Assembly loop, 배열, lea, pipe line) (0) | 2014.07.31 |
글
20140804 (Assembly procedure(함수 구현), call, ret, 지역변수, Entry Code, Exit Code)
116일차
---------------
Assembly
---------------
------- Procedure and Function
보통 void 형 함수를 Procedure(프로시저)라 부르고
return 값이 있는 함수는 Function이라 부르는데
굳이 구별하는 언어도 있고 하지 않는 언어도 있다.
--- 아래 예제 소스를 통해 함수 구현.
------- call Instruction
함수 호출, EIP를 Intel 에서는 건들 수 없지만
간접적으로 조작하는 명령어가 몇 가지 있는데
call 이 그 중 하나이다.
call 의 실행 순서
1. push eip
2. mov eip , 함수 주소
near 은 32 bit 주소 체계
far 은 64? bit 주소 체계
relative 는 현재로 부터 얼마나 떨어졌는지,
indirect 는 포인터 같은 개념이고,
direct 는 그 주소를 바로 가리킨다.
--- 위의 소스를 예제로 어떻게 돌아가는지 자세히 보기로 한다.
1. EIP를 보면 다음 실행 주소가 _start의 시작 주소이다.
2. 시작 주소(0x0040103E)를 보면 E8 CD FF FF FF (call Initialize)를 실행한다.
3. E8은 call 명령어에 operand 값이 near relative를 가리키는데
현재부터 얼마나 떨어져 있는지를 가리킨다.
4. Little Endian 이니 FF FF FF CD -> -51 만큼 떨어져 있다는 소리인데
어디서부터 떨어졌는지 기준점은 다음 실행 주소이니
다음 실행 주소 0x00401043으로 부터 -51(-0x33) 만큼 빼면 0x00401010이다.
5. 그래서 Initialize 가 실행된다.
------- ret Instruction
ret 는 다음을 수행한다.
- pop eip
ret 0 (C에서는 반환 값을 return 뒤에 넣는데,
Assembly에서는 무슨 sp?뭐시기 al 뭐시기 뭔 값이 들어간다고
C에서 하는 반환 값과는 좀 다르다고 하는데 아직은 잘 모르겠다.)
다음 실행 주소가 저장된다.
------- 지역변수
위의 그림과 같이 인수가 뒤에서 부터 스택에 들어간다.
인수가 많으면 많을수록 스택도 많이 차지하고 느려진다.
따라서 최적화를 위해선 구조체를 선언하여 그 주소 값을 넘기는 형식으로 하면 좋다.
------- Entry Code , Exit Code
- Entry Code
함수 호출시 stack 확보 등 준비 코드
- Exit Code
함수 해제시 stack 해제 등 마무리 코드
--- 예제를 통해 C에서 ASM 함수를 호출
- main.c
- main.c의 중간 .asm 파일
- smart()함수가 정의 된 smart1.asm
- 메모리 구조
return 값은 eax에 저장되어 있다.
main.asm에 call 명령어 다음에 add esp, 12 가 뭘 의미하는지 몰랐는데
smart() 함수를 호출 후 원래 esp 위치로 돌려주는 역할이다.
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140818 (Assembly CDECL, STDCALL, PE구조) (0) | 2014.08.18 |
---|---|
20140805 (Assembly 함수 return 값, 인수) (0) | 2014.08.05 |
20140801 (Assembly push, pop, pushad, popad, pushfd, popfd) (0) | 2014.08.01 |
20140731 (Assembly loop, 배열, lea, pipe line) (0) | 2014.07.31 |
20140730 (rounding factor, adc, sbb, clc, stc, cmc, jmp, cmp) (0) | 2014.07.30 |
글
20140801 (Assembly push, pop, pushad, popad, pushfd, popfd)
115일차
-------------
Assembly
-------------
------- Stack 영역
ESP Reg가 Stack영역의 주소를 갖고 있다.
Stack 영역은 높은 주소에서 낮은 주소로 움직인다.
------- push Instruction
stack 영역에 값을 넣는 명령어
push [저장할 값]
- push 100
이 명령어가 실행되는 과정.
1. ESP = ESP - 4;
2. *ESP = 100;
예제)
Stack은 메모리 영역이기에 little endian이라서
값이 거꾸로 들어간다.
차례대로 들어갔다.
(0x0012FFC0 인지 주소를 어떻게 알았냐면은
ESP에 값을 확인하면 된다.)
1 byte로는 들어가지 않고 4 byte로 들어간다.
부호에 맞게 남는 값이 채워져 들어갔다.
2 byte는 2 byte씩 들어간다.
2 byte가 들어가고 4 byte가 이어서 계속 들어가고
2 byte가 들어갔다.
C 컴파일어 같은 경우는
4 byte씩 끊어 넣기 때문에
줄줄 이어지지 않는 반면
어셈블리는 그대로 이어서 준다.
------- pop Instruction
Stack 영역에 값을 빼오는 명령
pop [저장할 곳]
- pop eax
이 명령어가 실행되는 과정.
1. eax = *ESP;
2. ESP = ESP + 4;
------- pushad, popad
--- pushad
Reg 값 저장
EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI
순으로 저장.
--- popad
Reg 값 불러오기
EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI 중에
ESP만 제외하고 다 불러온다.
pusha
=> push 16bit reg
pushad
=> push 32bit reg
popa
=> pop 16bit reg
popad
=> pop 32bit reg
--- pushad 예제)
--- popad 예제)
------- pushfd , popfd
flags 값을 저장한다.
- pushfd 예제)
a96인데 b96으로 저장된다.
TF flag가 켜지고 저장이된다.
- popfd 예제)
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140805 (Assembly 함수 return 값, 인수) (0) | 2014.08.05 |
---|---|
20140804 (Assembly procedure(함수 구현), call, ret, 지역변수, Entry Code, Exit Code) (0) | 2014.08.04 |
20140731 (Assembly loop, 배열, lea, pipe line) (0) | 2014.07.31 |
20140730 (rounding factor, adc, sbb, clc, stc, cmc, jmp, cmp) (0) | 2014.07.30 |
20140729 (Assembly imul, idiv, div, cbw, cwd, cdq, cwde, movsx, movzx) (0) | 2014.07.29 |
글
20140731 (Assembly loop, 배열, lea, pipe line)
114일차
--------------
Assembly
--------------
------- Conditional Jump Instruction 종류
--- 숫자 맞추기 게임을 통한 Assembly 예제 소스
------- loop Instruction
반복문
점프문과 비슷하나 일정 반복에 더 강점을 갖고 있다.
점프 범위는 -128 ~ 127 byte 이다.
이런식으로 사용한다.
ECX Reg와 관련이 있다.
(EAX, EDX는 계산 관련, EBX는 주소 관련 Reg이다.)
ECX의 값이 0이 될 때까지 계속 돈다.
--- 배열
지금까지 소스에서 문자열 배열을 가끔 봐 왔고
숫자 배열도 문자열 배열과 마찬가지로 선언한다.
Array DWORD 10 DUP (?)
C => int Array[10];
이렇게 사용한다.
--- lea Instruction
주소 값을 대입한다.
lea ebx , number1
C => ebx = &number1;
배열과 점프, lea 예제)
------- Pipe line
CPU가 명령을 실행하는 과정이 3가지가 있다.
- Fetch an instruction from memory 명령을 가져옴
- Decode the instruction 명령을 해석
- Execute the instruction 명령 실행
이것이 이어지는 것을 pipe line 이라고 한다.
그런데 여기서 문제가 jump문이 나올 때 이 pipe line이 깨지기 때문에
반복문, 제어문을 많이 사용하면 CPU의 효율이 떨어진다.
그렇다고 반복문, 제어문을 사용하지 않을 수 없으니
반복문과 제어문을 사용할 때 이런 것을 생각하고 작성해야 한다.
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140804 (Assembly procedure(함수 구현), call, ret, 지역변수, Entry Code, Exit Code) (0) | 2014.08.04 |
---|---|
20140801 (Assembly push, pop, pushad, popad, pushfd, popfd) (0) | 2014.08.01 |
20140730 (rounding factor, adc, sbb, clc, stc, cmc, jmp, cmp) (0) | 2014.07.30 |
20140729 (Assembly imul, idiv, div, cbw, cwd, cdq, cwde, movsx, movzx) (0) | 2014.07.29 |
20140728 (add, sub, inc, dec, neg, mul) (0) | 2014.07.28 |
글
20140730 (rounding factor, adc, sbb, clc, stc, cmc, jmp, cmp)
113일차
-----------------
Assembly
-----------------
------- rounding factor
라운딩 팩터
섭씨를 화씨로 변환하는 프로그램인데
변환 공식이 F = (9 / 5) * C + 32 이다.
그런데 소스 중에 빨간 줄이 쳐진 곳을 보면 2를 더한다.
왜 2 를 더할까?
rounding factor라고 하는데
9 / 5 = 1.8 이다.
정수간에 연산이기에 소수점 아래는 다 버리게 된다.
그래서 반올림 하여 2로 만들어 주어서 차이가 적게 만드려고 한다.
(9 + 2) / 5 = 2.2 로 2에 가깝게 만들어 주었다.
2 / 5 = 0.4 로 소수점 어떤 값에 0.4를 더해주게 되면
반올림된 값으로 쳐줄 수 있다. 그래서 정수 계산에서 2를 더해준다.
------- adc , sbb Instruction
adc (덧셈)
adc A , B
==> A = A + B + carry
sbb (뺄셈)
sbb A , B
==> A = A - B - carry
------- clc , stc , cmc Instruction
carry flag 셋팅.
------- jmp Instruction
무조건 점프
jmp offset(상대값)
------- 조건에 따른 점프
jz endwhile
zero flag 가 set 됐으면 endwhile로 점프
jnz startwhile
zero flag 가 0 이면 (연산 결과가 0이 아니다) startwhile로 점프
js endprg
sign flag 가 set 됐으면 (음수이면) endprg로 점프
jns smart
sign flag 가 0 이면 (양수이면) smart로 점프
------- cmp Instruction
비교
cmp operand1 , operand2
operand1 에서 operand2 를 뺀다.
뺀 값이 저장되는건 아니고 flags가 바뀐다.
그 flag가 바뀐 값으로 조건에 맞게 점프를 한다.
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20140801 (Assembly push, pop, pushad, popad, pushfd, popfd) (0) | 2014.08.01 |
---|---|
20140731 (Assembly loop, 배열, lea, pipe line) (0) | 2014.07.31 |
20140729 (Assembly imul, idiv, div, cbw, cwd, cdq, cwde, movsx, movzx) (0) | 2014.07.29 |
20140728 (add, sub, inc, dec, neg, mul) (0) | 2014.07.28 |
20140725 (Assembly Flags Register) (0) | 2014.07.25 |