|
메뉴릿
카테고리
최근 등록된 덧글
감사합니다. shell scrip..
by Mr.Carbin at 07/17 아.. 정말 감사드립니다.. by 송진영 at 03/15 조금 거리가 있는 주제.. by sio4 at 03/11 안녕하세요? 덧글 달아.. by 송진영 at 02/14 펄이나 파이썬은 진입장.. by kirrie at 02/13 최근 등록된 트랙백
Allergy to codeine s..
by Source of codeine. Online phentermine. by Lowest price for phen.. Tramadol ultram medic.. by Ultram addiction. Ephedra weight loss .. by Ephedra. Canada overnight am.. by Ambien manufacturer. Calico film music des.. by Zoo sex. Lexapro-ultracet-int.. by Extracting acetanin.. Ambien. by Ambien verses temac.. Scat eating shit sex. by Shit sex photos per.. Ordering adderall. by Adderall. 포토로그
이전블로그
이글루링크
이글루 파인더
|
2009년 05월 15일
원문 : http://www.drpaulcarter.com/pcasm/
번역 : 송진영( caddsjy@gmail.com ) 1.3.1 기계언어( Machine Language ) 모든 CPU들은 그들만의 언어(기계어)를 가지고 있다. 기계 명령어는 byte형태로 메모리에 기록된다. 각각의 명령어들은 Operation code 또는 줄여서 opcode라고 불리는 고유한 숫자 코드로 이루어져 있다. 80x86 프로세서의 명령어들은 크기가 다양하다. opcode는 항상 명령어의 맨 앞에 위치한다. 또한 많은 명령어들은 명령에 사용될 데이터(상수나 주소)를 포함하고 있다. 기계언어로 직접 프로그램을 작성하는 것은 매우 어렵다. 숫자로만 이루어진 코드를 사람이 읽고 분석하는 것은 매우 짜증날 만한 일이다. 예를들어 EAX와 EBX레지스터의 값들을 더한 결과를 EAX 레지스터에 기록하는 명령은 아래와 같은 Hex코드로 이루어진다. 03 C3 위와 같이 hex로만 이루어진 코드를 분석하는 것은 아주 어렵다. 다행히도 assembler라는 언어를 통하여 좀 더 편하게 작업이 가능하다. 1.3.2 어셈블리 언어 (Assembly language ) 어셈블리어는 text형태로 기록되어져 있다.( 고급언어와 같은.. ) 각 어셈블리 명령어는 1개의 기계언어로 표현된다. 예를 들어 위 1.3.1 기계언어의 예를 어셈블리로 작성하면 아래와 같다. add eax, ebx기계어와 비교하면 어셈블리어의 명령은 아주 읽기가 쉽다. add라는 단어는 덧셈 명령의 니모닉(mnemonic)이다. 일반적인 어셈블리 명령의 형태는 아래와 같다. : mnemonic operand(s)Assembler는 어셈블리 명령들이 기록된 텍스트 파일을 읽어서 기계언어로 변환한다. Compiler는 고급언어에서 유사한 역할을 한다. 어셈블러는 컴파일러와 비교하면 매우 단순하다. 모든 어셈블리언어의 명령어는 1개의 기계명령과 직접적으로 연관된다. 하지만 고급언어에서 한개의 명령어는 하나 이상의 기계명령이 사용될 수도 있다. 어셈블리언어와 고급언어들과의 또 다른 중요한 차이점은 모든 CPU마다 다른 기계명령어를 가지고있기 때문에 어셈블리 언어 또한 CPU마다 다르게 작성된다. 어셈블리로 작성된 프로그램을 다른 아키텍쳐의 컴퓨터로 이식하는 것은 고급언어와 비교하여 매우 어렵다. 이 책의 예제들은 Netwide Assembler(줄여서 NASM)를 기준으로 작성되어졌다. NASM은 인터넷에서 무료로 구할 수 있다. 다른 어셈블러로는 마이크로소프트사의 MASM, 볼랜드사의 TASM등이 있으며 모두 문법에 차이가 있다. 1.3.3 명령어 (Instruction operands) 기계코드 명령어는 다양한 숫자와 형식의 명령어들로 이루어져있다. 각 명령어들은 한정된 수의 오퍼랜드들을 가진다.(0~3개..) 오퍼랜드들의 종류로는 아래와 같다 :
1.3.4 기본 명령들(Basic instructions) 가장 기본적인 명령은 MOV 명령이다. 이 명령어는 데이터를 다른 곳으로 이동시킨다.( 고급언어의 대입연산자와 같은 역할이다. ) MOV 명령은 두개의 오퍼랜드를 가진다. mov dest, srcsrc의 데이터를 dest로 복사하게 된다. 이 명령어의 한가지 제약사항은 양쪽의 오퍼랜드들이 메모리 오퍼랜드가 아니여야한다. 여러가지의 명령어를 사용하는데에 있어서 임의의 규칙이 있다. 또한 오퍼랜드들은 반드시 크기가 같아야한다. AX의 값은 BL에 저장될 수 없다. 아래에 몇가지 예가 있다.( 세미콜론으로 시작되는 부분은 주석이다. ) mov eax, 3 ; EAX레지스터에 3을 기록한다.(3은 immediate 오퍼랜드이다. ) ADD명령은 정수의 덧셈에 사용된다. add eax, 4 ; eax = eax + 4 SUB명령은 정수의 뺄셈에 사용된다. sub bx, 10 ; bx = bx - 10 INC와 DEC명령은 값을 1증분하거나 감소시킨다. 1이라는 오퍼랜드가 implicit오퍼랜드이며 직접적으로 코드에 표기하지는 않는다. inc ecx ; ecx++ 1.3.5 지시어(Directives) 지시어는 실제적으로 CPU가 명령을 수행하는 것이아니고 어셈블러에서 사용하는 인위적인 지시어이다. 기계언어로 변환되지 않는다. 공통적으로 지시어가 사용되는 것은 아래와 같다. :
C언어에서는 #으로 시작되지만 NASM에서는 %로 시작된다. equ 지시어 equ 지시어는 symbol을 정의할 때 사용됩니다. 심볼들은 어셈블리 프로그램 내에서 사용될 상수에 이름을 부여한 것입니다. 형태는 아래와 같습니다. : symbol equ value이미 정의된 심볼의 값은 재정의 될 수 없습니다. %define 지시어 이 지시어는 C언어의 #define지시어와 유사합니다. C에서와 같이 상수의 정의를 위해 주로 사용됩니다.
위의 코드는 SIZE라고 정의된 macro를 MOV명령에서 사용하는 예입니다. Macro는 심볼을 유연하게 사용할 수 있습니다. 값을 재정의 할 수 있으며 좀 더 많은 상수 숫자를 사용할 수 있습니다. Data 지시어 Data 지시어는 메모리 공간에서 데이터 세그먼트를 정의할 때에 사용됩니다. 두 가지 종류의 메모리 할당이 가능합니다. 첫번째로는 데이터공간 만을 정의하고 두번째로는 데이터 공간을 정의한 뒤에 초기값을 지정하는 것입니다. 첫번째 방식에서는 RESX지시어를 사용합니다. RES다음의 X문자는 저장될 객체의 크기를 나타내는 기호를 사용합니다. 아래 표 1.3에 사용가능한 기호들의 목록이 있습니다. ------표 1.3 RESX와 DX 지시어에 사용되는 기호----- 단위 | 기호 byte | B word | W double word | D quad word | Q ten bytes | T -------------------------------------------------------------- 두 번째 방식( 메모리 할당 후 초기값 지정.. )은 DX지시어를 사용합니다. RESX지시어와 마찬가지로 D다음의 X문자는 데이터의 크기를 나타내는 표1.3의 기호들 중 하나가 사용됩니다. 일반적으로 메모리의 위치를 나타낼 label을 사용합니다. Label은 코드내에서 메모리의 위치를 참조하기 쉬운 방법을 제공합니다. 아래에 몇가지 예제가 있습니다. : L1 db 0 ; L1이라는 Label, byte크기만큼을 가지고 0으로 초기화 됨 큰따옴표나 작은따옴표는 동일한 효과를 가집니다. 연속적으로 정의된 데이터들은 메모리에 순차적으로 기록됩니다. 위의 예에서 L2는 메모리상에서 L1바로 다음에 기록됩니다. L9 db 0, 1, 2, 3 ; 4 byte들로 정의됩니다. DD 지시어는 정수나 단정도 부동 소수점(C언어의 float 자료형과 같은) 상수를 정의하는데 사용됩니다. 하지만 DQ는 오로지 배정도 부동소수점( double precision floating point ) 상수를 정의할 수만 있습니다. 한 번에 많은 크기의 변수를 할당하기 위해서 NASM에서는 TIMES지시어가 유용하게 사용됩니다. 이 지시어는 오퍼랜드의 수 만큼 반복됩니다. L12 times 100 db 0 ; db 0을 100개 만든것과 같습니다. Label들은 코드내에서 데이터의 위치를 참조하는데 사용한다는 것을 기억하십시요. Label은 두가지 방식으로 사용될 수 있습니다. 만약 Label이 그냥 사용되면 data의 주소(또는 offset)로 해석되고 만약 사각 괄호([])로 둘러쌓여 사용되면 이것은 주소상에 위치한 데이터로 해석됩니다. 다른 말로 표현한다면, 첫 번째는 데이터의 포인터로 사용되고 두 번째는 포인터가 가리키는 데이터로 말할 수 있습니다.(C언어에서 포인터를 나타내는 *문자와 같습니다, MASM이나 TASM에서는 다르게 사용됩니다.) 32비트 모드에서 주소는 32비트까지 지정이 가능합니다. 아래에 몇가지 예가 있습니다. mov al, [L1] ; L1의 값을 AL로 복사위 예에서 7번째 줄의 예는 NASM만의 중요한 속성을 보여줍니다. 어셈블러는 lable이 참조하고 있는 데이터의 타입에 대해서는 조사하지 않습니다. 프로그래머가 Label을 정확하게 사용해야합니다. 이 점은 C언어의 포인터변수와 유사합니다. 한번 더 강조하면 포인터가 정확하게 사용되었는지는 검사하지 않습니다. 이 경우에 어셈블리는 C보다 더 많은 에러가 발생할 수 있습니다. 아래 명령어를 예로 보면 : mov [L6], 1 ; L6에 1을 기록 이 문법은 operation size not specified 에러를 발생할 것입니다. 왜냐하면 어셈블러는 1이라는 값이 byte형인지 word형인지 double word형인지 알 수 가 없기 때문입니다. 이 문제를 해결하기 위해서는 size 지시어를 추가합니다. : mov dword [L6], 1 ; L6에 1을 기록합니다.위 명령어는 L6주소를 시작으로 double word 크기만큼의 메모리 공간에 1을 기록하라는 것을 나타냅니다. 또 다른 크기를 지정하는 지시어들은 다음과 같습니다. BYTE, WORD, QWORD, TWORD (TWORD는 메모리에 10byte 영역을 정의합니다. )
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
| |||||