수안이의 컴퓨터 연구실

  • Mainpage
  • About Me
  • Tags
  • Metapage
  • Notice
  • Location
  • Keywords
  • Guestbook
  • Admin
  • Write an Article
  • Total | 1620990
  • Today | 370
  • Yesterday | 482

38 Articles, Search for 'Programming/Assembly'

  1. 2007/03/15 CPU 레지스터
  2. 2006/07/10 반복 출력, REPEAT 디렉티브 & 연산자, 링크드 리스트 예제
  3. 2006/07/10 UNION 사용하기, 매크로란? 매크로 정의하기, 매크로 호출하기 LABEL
  4. 2006/07/10 구조체란? 구조체 선언, 구조체 변수 사용하기
  5. 2006/07/10 버블소트
  6. 2006/07/10 스트링 비교 예제, 이차원 배열, 베이스-인덱스 디스플레이스먼트
  7. 2006/07/10 스트링관련 인스트럭션들, REP 접두어, 방향 플래그(Direction Flag)
  8. 2006/07/10 프로시져 호출 규약, LEA 인스트덕션
  9. 2006/07/10 INVOKE 디렉티브, 스택파라미터를 사용하는 프로시져의 정의, PROTO 디렉터
  10. 2006/07/10 LOCAL 디렉티브, 스택파라미터
«Prev  1 2 3 4  Next»
Programming/Assembly2007/03/15 11:20

CPU 레지스터

원본 : http://www.debuglab.com/knowledge/register.html

1.요약

CPU 레지스터에 대해서 알아봅니다.


2.본문

CPU 에서 사용되는 레지스터의 종류는 아래와 같습니다.

AX     Accumulator 

BX     Base register 

CX     Counting register 

DX     Data register 

DS     Data Segment register 

ES     Extra Segment register 

SS     Battery segment register 

CS     Code Segment register 

BP     Base Pointers register 

SI     Source Index register 

DI     Destiny Index register 

SP     Battery pointer register 

IP     Next Instruction Pointer register 

F      Flag register 



- 2001.08.13 Smile Seo -
"Assembly" 카테고리의 다른 글
  • CPU 레지스터 (0)2007/03/15
  • 반복 출력, REPEAT 디렉티브 & 연산자, 링크드 리... (0)2006/07/10
  • UNION 사용하기, 매크로란? 매크로 정의하기, 매크... (0)2006/07/10
  • 구조체란? 구조체 선언, 구조체 변수 사용하기 (0)2006/07/10
  • 버블소트 (0)2006/07/10
2007/03/15 11:20 2007/03/15 11:20
Posted by webdizen
Tags Register
No Trackback No Comment

Trackback URL : http://www.webdizen.net/blog/trackback/2691

Leave your greetings.

[로그인][오픈아이디란?]

Programming/Assembly2006/07/10 00:55

반복 출력, REPEAT 디렉티브 & 연산자, 링크드 리스트 예제

반복 출력, REPEAT 디렉티브 & 연산자, 링크드 리스트 예제

  • 반복 블럭

    반복 블럭은 어셈블리어 구문들을 여러번 반복하게 해주는 '디렉티브'이다. 이들의 특징은 반복횟수가 상수에 의해 결정된다는 것이다. 이들은 우리가 흔히 아는 반복문과는 약간 다르다. 지금 말하는 반복 블럭은 일종의 매크로와 같은 역할을 하는 것임을 깊이 새기기 바란다.
    반복 블럭에는 WHILE, REPEAT, FOR, FORC 등이 있는데, 대표적으로 숫자에 적용되어 가장 자주 쓰이는 REPEAT에 대해서 알아보자.

  • REPEAT 디렉티브

    다른 반복 디렉티브들은 수식, 심볼, 문자에 대해 반복하는 반면, REPEAT 디렉티브는 상수수식의 값만큼 반복하기 때문에, 그만큼 쓰임새가 크다.

    REPEAT 상수수식 구문들... ENDM
    직접 써보지 않으면 느낌이 오지 않을 것이다. 아래와 같은 코드가 어떤 일을하게 될지 추측해 보라.

    .data array LABEL DWORD iVal = 10 REPEAT 100 DWORD iVal iVal = iVal + 10 ENDM
    위와같은 코드는 루프를 100번 돌면서 다음과 같은 배열을 만들 것이다.

    array DWORD 10, 20, 30, 40, ... 1000
    원소의 사이즈는 4바이트이고 총 100개의 원소를 갖게 된다. 따라서 REPEAT디렉티브는 많은 변수를 선언하고 초기화할 때 유용하다. 다시한번 말하지만 반복블럭은 일종의 매크로이며 반복회수만큼 코드를 붙여넣는다는 것을 잊지 않기 바란다.

  • $ 연산자

    이 연산자는 조금은 특이한 연산자이다. 예제를 먼저 살펴보자.

    list WORD 10, 20, 30, 40 ListSize = ($ - list) / 2 ; ListSIze는 4
    list의 사이즈를 구하는데 $연산자를 이용하였다. $는 이 연산자가 쓰인 위치의 오프셋을 리턴해준다. 쉽게 이야기하면 $가 쓰일 자리에 변수가 정의되었다면 그 변수가 갖게 되었을 '데이터 세그먼트 시작부분으로부터의 거리(Offset)'를 리턴해 준다는 뜻이다(이 Offset을 흔히 주소라고도 부른다). 쉽게 말하면 $는가장 최근에 정의한 데이터의 바로 다음 주소를 리턴해 준다는 말이다. 위의 예에서 $는 메모리상에서 list 배열 네번째 원소의 바로 뒤를 가리키며, list는 배열의 첫 번째 인덱스를 가리키므로 ($ - list)는 8이 된다. 왜 4가 아니고 8이냐는 궁금증이 생긴다면, list배열이 WORD형으로 되어있음을 다시한번 눈여겨 보시기 바란다.

  • 링크드 리스트 예제

    본회에서 배운 내용을 복습하는 의미에서 링크드리스트를 사용하는 간단한 프로그램을 작성해 보겠다.
    링크드 리스트(Linked List)는 연결리스트라고도 하며, 각각의 노드를 포인터를 이용하여 연결함을로써 구현된다. 그림 2와 같은 구조를 떠올리면 이해하기 쉬울 것이다.(사실 여기까지 강좌를 읽으며 이해하고 계신 분이라면 충분히 알고 있을 것이다.) 그림 2는 단방향의 링크드리스트를 나타낸다.

    <그림 2 : 링크드 리스트(linked list)>
    링크드 리스트를 구현해 보았다면 알겠지만 구조체를 사용해야 한다. 링크드 리스트를 위한 구조체를 정의할 때 반드시 다음 노드의 주소를 갖는 필드를 적어 주어야 함은 말할 밀요도 없다.

    이제 구조체를 정의해 보자. 구조체의 정의는 너무나도 간단하다.

    ListNode STRUCT NodeData DWORD ? ; 노드의 데이터값을 갖는다. NodePtr DWORD ? ; 다음 노드의 주소를 갖는다. ListNode ENDS
    한 회 내에서 데이터 추상화된 링크드 리스트를 만드는 것은 무리이므로, 최대한 간단히 다음과 같이 링크드리스트를 미리 만들어 놓겠다. 이것은 물론 .data에 들어갈 코드이다.

    TotalNodeCount = 15 NULL = 0 Counter = 0 .data LinkedList LABEL DWORD ; (1) REPEAT TotalNodeCount ; (2) Counter = Counter + 1 ; (3) ListNode <Counter, ($ + (Counter * SIZEOF ListNode))> ENDM ListNode <0, NULL> ; (4) 꼬리노드
    첫번째 줄에서 세번째 줄 까지는 단지 기호상수의 정의에 불과하므로 .data이하부터 설명하겠다. 이곳은 헷갈리기 쉬우니 눈여겨 보기 바란다.
    (1) 먼저 LABEL디렉티브가 나왔는데, LABEL디렉티브 뒤에 나온 DWORD는 형식적인 것이다. 왜냐하면 나중에 사용할 때는 어차피 ListNode인 것처럼 사용하기 때문이다. LinkedList라는 데이터 레이블은 링크드리스트 첫 번째 노드에 대한 데이터 레이블로 쓰이게 된다.
    (2) REPEAT디렉티브는 첫 번째 인자의 상수값만큼(여기서는 15) 루프를 돌리게 된다.
    (3) 따라서 Count가 1씩 증가되면서 15개의 ListNode가 선언된다. 위 코드에서는 선언과 동시에 초기화를 시켜주고 있는데, 두 번째 필드에서는 ($ + (Counter * SIZEOF ListNode))을 이용하여 다음 노드의 오프셋을 얻어온다. $값은 LinkedList레이블이 가리키는 오프셋을 갖고, REPEAT블럭 내에서 변하지 않는다. 왜냐하면 루프가 돌기 이전에 $연산자가 계산되기 때문이다.
    (3) 결과적으로, 꼬리노드를 포함한 16개의 노드가 모두 연결된다.

    이제 본격적으로 main프로시져를 정의해 보겠다. 다음의 코드는 데이터 영역에서 만든 링크드 리스트를 탐색하며 각각의 NodeData를 찍고난 후 종료한다.

    .code main PROC ; (1) mov esi, OFFSET LinkedList ; NodeData 필드의 모든 정수들을 보여준다. NextNode: ; (2)꼬리노드인지 체크해 본다. mov eax, (ListNode PTR [esi]) .NextPtr cmp eax, NULL je quit ; (3)NodeData를 출력한다. mov eax, (ListNode PTR [esi]) .NodeData call WriteDec call Crlf ; (4)포인터를 다음 노드로 옮긴다. mov esi, (ListNode PTR [esi]) .NextPtr jmp NextNode quit: exit main ENDP END main
    (1) 링크드 리스트의 시작 주소를 esi에 넣어둔다. 이제 esi는 노드를 가리키는 포인터로 쓰일 것이다.
    (2) 루프를 계속 돌 것인지를 결정하는 부분이다. esi가 가리키는 주소에 존재하는 ListNode형 구조체변수의 NextPtr이라는 필드를 읽어서 eax에 넣는다. 물론 eax에 넣는 이유는 NULL인지 판단하기 위해서다. NextPtr필드가 NULL이라는 것은 더이상 다음 노드가 없다는 뜻이기 때문이다. 만약 NULL이라면 quit레이블로 점프하여 프로그램을 종료하게 된다.(NULL은 데이터 영역에서 정의한 기호상수이며 0과 같다.)
    (3) esi가 가리키는 주소에 존재하는 ListNode형 구조체변수의 NodeData필드의 값을 eax에 읽어들인 뒤, 해당 데이터를 출력하고 개행문자를 출력한다. 개행문자는 우리가 텍스트 에디터에서 엔터를 누를 때와 같은 효과를 내는 문자이다.
    (4) 현재 esi가 가리키는 ListNode형 구조체변수의 NextPtr필드 값을 다시 esi에 복사해 넣는다. 따라서 esi는 다음 노드의 주소를 갖게 될 것이다. 그 다음 다시 NextNode레이블로 돌아가서 지금까지 해온 과정((2)~(4))을 반복한다.

  • 강좌를 마치며...

    이번 회에서는 구조체와 매크로에 대해 배워보았다. 적어도 한 가지의 고급언어를 프로그래밍해보신 여러분들은 어셈블리어를 보면서 자신이 다뤘던 프로그래밍 언어들이 어떻게해서 어셈블리어로 구현될지에 대해서도 머릿속에 조금씩 떠오르리라 믿는다. 다음 회에서는 32비트 윈도우즈 프로그래밍을 간단히 배워볼 것이다. 그러나 직접 어셈블리어로 윈도우 프로그래밍을 하는 것은 단지 창 하나 띄워보는 정도로 그치고, IA-32의 메모리 관리방법에 좀더 중점을 두고 집필할 예정이다. 이쪽을 배우는 것이 좀더 여러분에게 도움이 될 것 같아서이다. 다음 회에는 좀더 흥미로운 주제로 여러분에게 다가갈 생각이다. 그럼 이만 줄이겠다.

  • "Assembly" 카테고리의 다른 글
    • CPU 레지스터 (0)2007/03/15
    • 반복 출력, REPEAT 디렉티브 & 연산자, 링크드 리... (0)2006/07/10
    • UNION 사용하기, 매크로란? 매크로 정의하기, 매크... (0)2006/07/10
    • 구조체란? 구조체 선언, 구조체 변수 사용하기 (0)2006/07/10
    • 버블소트 (0)2006/07/10
    2006/07/10 00:55 2006/07/10 00:55
    Posted by webdizen
    No Trackback No Comment

    Trackback URL : http://www.webdizen.net/blog/trackback/1740

    Leave your greetings.

    [로그인][오픈아이디란?]

    Programming/Assembly2006/07/10 00:52

    UNION 사용하기, 매크로란? 매크로 정의하기, 매크로 호출하기 LABEL

    UNION 사용하기, 매크로란? 매크로 정의하기, 매크로 호출하기 LABEL

  • UNION 사용하기

    UNION은 흔히 공용체라고 부르기도 한다. 구조체와 생김새는 비슷하지만 한 가지 다른 점은 모든 멤머가 같은 메모리 공간을 사용한다는 것이다. 즉, UNION에 세 개의 필드가있다고 할 때, 이 세 가지 중 한가지만 사용할 수 있다는 것이다. 따라서 UNION의 크기는 세 필드중 사이즈가 가장 큰 필드의 크기와 같다. 다음과 같이 정의하면 된다.

    유니온이름 UNION 필드들... 유니온이름 ENDS

    또한 구조체의 필드중 몇몇의 필드만 묶어서 UNION으로 정의할 수 있다.

    구조체이름 STRUCT 구조체필드들... UNION 유니온필드이름 유니온필드들... ENDS 구조체이름 ENDS

    약간 복잡해 보이지만 사실은 '유니온필드들'만 유니온으로 감쌌을 뿐이다. 유니온필드에 접근할 때는 '구조체이름.유니온필드이름.유니온필드' 로 접근하면 된다. 지금까지 언급한 특징만 다를 뿐이지, 사용하는 방법에 있어서 유니온과 구조체는 차이점이 없다. 위와같이 하는 것이 헷갈린다면 먼저 유니온을 정의한 후, 구조체 필드에 유니온 변수를 선언하면 된다. 그리고 하는 일은 두 가지 방법이 완전히 같다.

    몇몇 독자는 UNION을 과연 어디에 쓰게 될지 궁금해 하실지 모르겠다. 작성하는 프로그램이 메모리를 매우 적게 차지해야하는 경우, 구조체의 멤버 중 동시에 쓰이지 않는 멤버를 유니온으로 묶어서 사용하면 메모리를 절약할 수 있다. 이와는 달리 유니온만의 특성을 이용한 예가 있다. 바로 IP주소에 대한 것이다. 소켓 프로그래밍을 해보신 분은 알겠지만 IPv4에서 IP주소는 4바이트이다. 우리가 눈으로 볼 때는 이 4바이트의 IP주소를 1바이트씩 잘라 읽어야 편리하다는 것을 잘 알고 있을 것이다. (우리가 잘 알고 있는 203.253.21.151의 형태) 이러한 경우 UNION을 유용하게 써먹을 수 있다.

    IP UNION inDword DWORD 0 inByte BYTE 0 0 0 0 IP ENDS
    IP.inDword에 4바이트의 IP주소를 넣고, IP.inByte , IP.inByte + 1, IP.inByte + 2, IP.inByte + 3으로 하나씩 값을 읽으면 우리가 읽기 편한 형태가 될 것이다. 다만 여기서 인텔 계열의 CPU는 리틀엔디안 오더를 사용하기에 우리가 흔히 생각하는 것과는 반대의 순서로 읽어야 한다는 점에 유의해야할 것이다.(3회 참고)

  • 매크로란?

    매크로란, 어셈블리 구문들을 하나로 묶어놓은 것이다. 겉으로 보기엔 프로시져와 매우 유사한 형태를 갖고 있다. 하지만 C에서의 매크로 함수와 같아서, 스택에 수많은 push와 pop을 해가며 함수를 호출하는 것이 아니라, 단지 코드가 덧씌워질 뿐이다. 따라서 속도는 매우 빠른 장점을 지닌 반면, 조심해서 사용하지 않으면 코드가 덧씌워지기 때문에 프로그램의 크기가 매우 커질 것이다. 다음과 같은 매크로가 정의되어있다고 하자.

    NewLine MACRO call Crlf ENDM

    이 매크로는 단지 화면에 개행문자(텍스트 에디터에서 엔터를 누른 것과 같은 효과)를 찍는 일만 수행한다. 매크로를 어떻게 정의하는지 대한 정확한 설명은 다음 단락에 이어질 것이다.

    .code NewLine

    위와 같은 코드는 전처리기(어셈블러가 컴파일하기 전에 수행된다)에 의해 다음과 같이 바뀐다.

    .code call Crlf

  • 매크로 정의하기

    매크로는 소스코드의 어느 부분에서도 정의될 수 있다. 하지만 매크로는 소스코드에서 정의되기 이전에 호출될 수는 없다.

    매크로이름 MACRO 파라미터1, 파라미터2, ... 구문들 ENDM
    정의는 위와 같이 한다. 매크로가 단순히 텍스트 치환보다 좋은 이유는 바로 파라미터를 넘길 수 있다는 점이다. 다만 조심할 점은 파라미터의 값이 매크로 내부로 넘어가는 것이 아니라는 점이다. 매크로는 단지 코드를 복사해주는 일만 하기 때문에, 코드 수준에서 파라미터를 인자로 넘어온 변수이름으로 치환하는 것에 불과하다. 만약 호출 시에 매크로가 요구하는 파라미터 개수보다 적은 개수가 넘어온다면 나머지는 빈칸으로 남겨진다. 이런 경우 대부분 구문 오류가 발생할 것이다.
    다음은 인자로 넘어온 문자를 화면에 찍어주는 일을 하는 매크로이다.

    mPutchar MACRO char push eax mov al, char call WriteChar pop eax ENDM

  • 매크로 호출하기

    매크로를 호출하려면 다음과 같이 사용한다.

    매크로이름 인자1, 인자2,...
    이제 실제로 매크로를 호출한 경우 코드에 어떤 일이 일어나는지 직접 살펴보자. 윗 문단에서 정의한 mPutchar를 예로 들어 설명하겠다.

    mPutchar 'A'
    라고 사용한 경우, 컴파일되기 전에 코드는 다음과 같이 변환된다.
    push eax mov al, 'A' call WriteChar pop eax
    코드는 위와 같이 변환된다. 다시한번 강조하지만 매크로의 파라미터는 단순한 텍스트 치환이다.

  • LABEL 디렉티브

    사실 LABEL디렉티브는 구조체나 매크로와는 그다지 관련이 있지 않다. 하지만 이 디렉티브를 언급하는 이유는 나중에 나올 링크드 리스트 예제에 이것이 나오기 때문이다. 크게 어려운 내용이 아니니 부담없이 읽어주기 바란다.
    4회에서 나왔던 내용이지만, 다시한번 변수에 대한 이야기를 해 보겠다. .data에 선언된 변수의 이름은 레이블이다. 우리가 흔히 '라벨'이라고 부르는 것을 떠올리면 레이블의 역할이 뭔지 알 수 있을 것이다. 우리가 선언한 데이터들은 데이터 세그먼트에 들어가게 되고 이 데이터 세그먼트의 시작부분으로부터 선언된 데이터가 존재하는 곳 까지의 거리(Offset)를 통해서 그 데이터에 접근하게 된다. 여기서 '거리'라고 하는 것은 숫자이기 때문에 사람이 기억하기가 어렵다. 따라서 각각의 '거리'에 대한 레이블을 하나씩 만들어놓은 것이 데이터 레이블인 것이다.

    LABEL디렉티브는 데이터 세그먼트에 이미 존재하는 변수에 또 하나의 이름과 타입을 지정해주는 데 이용된다. 다음의 사용예를 보아라.

    .data val16 LABEL WORD val32 DWORD 12345678h .code mov ax, val16 ; AX = 5678h mov dx, val16 + 2 ; DX = 1234h
    ax와 dx에 들어간 값이 뒤바뀐것 같다는 생각이 든다면 본 강좌 3회에 있는 리틀엔디안 오더를 다시 보기 바란다.

  • "Assembly" 카테고리의 다른 글
    • CPU 레지스터 (0)2007/03/15
    • 반복 출력, REPEAT 디렉티브 & 연산자, 링크드 리... (0)2006/07/10
    • UNION 사용하기, 매크로란? 매크로 정의하기, 매크... (0)2006/07/10
    • 구조체란? 구조체 선언, 구조체 변수 사용하기 (0)2006/07/10
    • 버블소트 (0)2006/07/10
    2006/07/10 00:52 2006/07/10 00:52
    Posted by webdizen
    No Trackback No Comment

    Trackback URL : http://www.webdizen.net/blog/trackback/1739

    Leave your greetings.

    [로그인][오픈아이디란?]

    Programming/Assembly2006/07/10 00:52

    구조체란? 구조체 선언, 구조체 변수 사용하기

    구조체란? 구조체 선언, 구조체 변수 사용하기

  • 시작하기에 앞서...

    어느덧 본 강좌도 끝을 향해 가고 있다. 이제 우리는 최소한 어셈블리어 코드를 보고 어떤 일을 하는지 정도는 파악할 수 있지만, 아직 뭔가 허전함을 느낄지 모르겠다. 본 회에 배울 구조체와 매크로에 관련된 내용은 그러한 허전함을 채워주리라 믿어 의심치 않는다.

    다른 언어도 마찬가지이지만, 나중에 버전업이 되어 새로운 것이 나오더라도 예전에 사용하던 형식과 개념 등은 그대로 묻어있게 마련이다. 어셈블리어도 마찬가지인데, 특히나 다른 프로그래밍언어에서 흔히 쓰이는 것이 어셈블리어에 약간 원초적(?)인 모습으로 존재하는 것을 볼 수 있다. 여기서 원초적이라는 말은 좀더 사용하기 불편하고 원시적으로 생겼다는 이야기이다. 필자는 어셈블리어의 프로시져나 배열, 구조체, 매크로 등을 처음 접할 때도 이러한 사실을 느끼고는 매우 흥미로워 했던 기억이 난다. 여러분도 기존에 사용하던 언어에 존재하던 클래스나 구조체, 매크로 등이 어셈블리어에 좀더 원초적(?)으로 존재하는 것을 배우며 희열을 느껴보길 바란다.

  • 구조체란?

    다른 프로그래밍 언어를 접해보신 분이라면 구조체가 무엇인지는 잘 알고 계실 것이다. 그래도 형식상 간단히 설명하자면 구조체는 개념적으로 연관있는 변수들의 그룹이자 틀이며 데이터형이다. 물론 이렇게 설명한다고 해서 이해하시는 분은 아무도 없을 것이다. 구조체를 하나 간단히 정의해 보겠다.

    COORD STRUCT X WORD ? Y WORD ? COORD ENDS

    위 구조체의 이름은 COORD이며 이것이 곧 데이터형이 된다. 뒤에 STRUCT라고 적힌 것을 보면 구조체를 말하는 것이라 추리할 수 있다. 또 마지막에 ENDS가 보이는데, 추측해 보건데, END Struct의 약자일 것이다. 보다시피 구조체의 정의는 너무나 간단하다. 구조체에 포함된 하나하나의 변수는 필드(field)라 불리우며, 멤버변수라고도 부른다. 그리고 ?표시를 한 곳은 초기화를 하지 않겠다는 뜻이다.
    구조체에 관련되어 배울 항목은 정의, 선언, 구조체변수 참조 이다. 하나하나씩 항목별로 배워보자.

  • 구조체의 정의

    구조체의 정의는 다음과 같이 한다.

    구조체이름 STRUCT 필드선언들... 구조체이름 ENDS

    구조체를 정의할 때는 초기값을 같이 넣어줄 수 있다. 초기값을 적는 형식은 우리가 일반 변수를 선언할 때와 같다. 다음의 예를 보자.
    Employee STRUCT IdNum BYTE "000000000" LastName BYTE 30 DUP(0) Years WORD 0 SalaryHistory DWORD 0, 0, 0, 0 Employee ENDS

    <그림 1 : Employee 구조체>

    첫번째 필드 IdNum을 보자. 스트링을 초기값으로 정해 놓았다. 숫자'0' 9개와 널문자 0, 총 10바이트가 들어간다. 잘 이해가 가지 않으면 3회를 다시 참고하기 바란다. 두번째 필드 LastName은 바이트원소가 30개 들어가는 배열에 초기값으로 모두 0을 넣어 두었다.(비어있는 스트링과 같기 때문에 그림1에서는 (null)이라고 적어 놓았다) 세번째 필드 Years는 WORD형으로 0을 하나 갖는다. 마지막 필드는 SalaryHistory로써 DWORD형 원소 4개에 각각 초기값을 0으로 넣어두었다. 두말할 필요도 없이 초기화를 하고 싶지 않으면 ?를 사용하면 된다.

    한가지 유의할 것은 위에 적어놓은 것은 구조체의 정의라는 것이다. 따라서 일종의 데이터 타입이 하나 생긴 것이고, 이를 사용하려면 구조체 변수를 선언해서 사용해야 한다.

  • 구조체의 선언

    좀 더 엄밀히 말하면 구조체에 대한 인스턴스의 선언 또는 구조체 변수의 선언이다. 두말할 필요도 없이 다음의 예제를 보면 쉽게 이해갈 것이라 믿는다. COORD는 본 회의 "구조체란?"단락에서 정의해 놓았던 그 구조체이다.

    .data point1 COORD <5, 10> point2 COORD <> point3 COORD {}

    이렇게<와 >를 사용하여 초기화를 해준다. 만약 < 와 >안에 아무것도 적어주지 않는다면 각 필드에 구조체의 정의에서 적어놓았던 초기값이 적용된다. <와 > 대신 { 와 }을 사용해도 무방하다. 이제 다음 구문을 보고 무슨 뜻일지 한번 생각해 보자.
    person3 Employee <, "Jones">

    눈치가 빠른 분은 이미 눈치챘을 것이다. 두번째 필드만 프로그래머가 지정한 초기값으로 초기화 하고 나머지는 디폴트 초기값으로 적용시키게 된다. 마지막으로 , 구조체의 배열은 어떻게 사용하는지 고민해 보자.
    AllPoints COORD 3 DUP (<0,0>)

    이제 COORD형 구조체 변수가 세 개 생겼고 구조체의 배열로 사용할 수 있게 되었다.
    지금까지는 구조체 변수를 선언하는 방법이었고, 다음 단락에서는 직접 구조체 변수를 사용하는 법을 배워보자.

  • 구조체 변수 사용하기

    구조체 변수를 사용하는 것은 놀랍게도 C언어와 다를 바가 없다. '.'을 이용하여 멤버에 접근하기 때문이다.

    .data worker Employee <> .code mov worker.SalaryHistory, 20000 ; 첫번째 봉급 mov worker.SalaryHistory + 4, 30000 ; 두번째 봉금

    C와 비슷하게 쓴다고 해서 마지막 줄의 코드까지 헷갈리지 않길 바란다. + 4를 했는데도 두번째 봉급이 된 이유는 DWORD타입(4바이트를 차지)이기 때문이다. 또 배열이라고 해서 다른 언어처럼 특별한 접근방식이 존재하는 것이 아니라 단지 주소에 덧셈을 하여 다음 원소로 접근한다는 것도 잊지 않기 바란다.

    이제 인다이렉트 오퍼랜드로 어떻게 접근하는지 알아보자. 인다이렉트 오퍼랜드는 4회에서 언급한 바 있다. 쉽게말하면 포인터로 접근하는 방법이다.


    mov esi, OFFSET worker mov ax, (Employee PTR [esi]).Years

    [esi].Years로 사용하는 실수를 범하지 않길 바란다. 구조체는 어셈블리에서 매우 잘 정의되어 있으며 사용하는데 있어 크게 어려울 것이 없다는 것을 느꼈을 것이다.

  • "Assembly" 카테고리의 다른 글
    • 반복 출력, REPEAT 디렉티브 & 연산자, 링크드 리... (0)2006/07/10
    • UNION 사용하기, 매크로란? 매크로 정의하기, 매크... (0)2006/07/10
    • 구조체란? 구조체 선언, 구조체 변수 사용하기 (0)2006/07/10
    • 버블소트 (0)2006/07/10
    • 스트링 비교 예제, 이차원 배열, 베이스-인덱스 디... (0)2006/07/10
    2006/07/10 00:52 2006/07/10 00:52
    Posted by webdizen
    No Trackback No Comment

    Trackback URL : http://www.webdizen.net/blog/trackback/1738

    Leave your greetings.

    [로그인][오픈아이디란?]

    Programming/Assembly2006/07/10 00:45

    버블소트

    버블소트

  • 버블소트

    이번엔 버블소트를 배워보도록 하겠다. C를 할 줄 안다면 버블소트 정도는 잘 알 테지만, 어셈블리어로 어떻게 구현되는지 한번 유심히 살펴보길 바란다.
    버블소팅을 해주는 프로시져를 하나 정의해 보겠다.

    BubbleSort PROC USES eax ecx esi, pArray:PTR DWORD, Count:DWORD mov ecx, Count dec ecx L1: push ecx mov esi, pArray L2: mov eax, [esi] cmp [esi+4], eax jge L3 xchg eax, [esi+4] mov [esi], eax L3: add esi, 4 loop L2 pop ecx loop L1 L4: ret BubbleSort ENDP

    < 그림 3 : 버블소트 >
    내부적으로 eax, ecx, esi레지스터를 쓰기에 USES 디렉티브를 사용하여 프로시져 호출 전과 후에 각 레지스터 값이 변하지 않게 하였다. 첫번째 인자로 DWORD형 배열에 대한 주소를 넘겨받고 두번째 인자로 배열 내의 원소수를 넘겨받는다. 물론 호출시 주소를 넘길 때는 ADDR연산자를 사용해야 한다는 것을 잊지 않기 바란다.

    우선 루프가 두개 있음을 진한 글씨를 통해 알 수 있을 것이다. 바깥루프가 한 번 도는 동안 어떤 변화가 일어나는지는 그림3을 참고하면 이해가 빠를 것이다.

    L1레이블 이전까지를 살펴보자. 버블소트에서 바깥 루프는 (원소의 개수 - 1)만큼 돌게 되므로 ecx에 값을 대입시킨다.
    L1레이블은 바깥 루프의 시작부분이다. 여기서 ecx를 스택에 넣는 것은 이중 루프를 돌리기 위함이다. 두 루프가 모두 ecx를 카운터로 사용한다는 점을 염두해 두면 이해할 수 있을 것이다. 그리고 esi에 배열의 시작주소를 넣는다.
    L2레이블은 안쪽 루프의 시작부분으로서, esi가 가리키는 원소와 그 다음 원소를 비교해서 순서가 맞지않을 경우 두 자료를 교환해준다. 만약 순서가 맞아서 교환할 필요가 없다면 L3로 점프하게 된다. 즉, 교환하지 않는다.
    L3레이블에서는 esi가 다음 원소를 가리키게 하고, (여기서 DWORD형이기 때문에 4를 증가시킨 것임을 알아두어라) 아까 스택에 넣어두었던 ecx를 꺼내게 된다. 다시 한번 말하지만, 이는 이중루프를 돌리기 위한 것이다.
    L4레이블은 함수를 종료하는 부분이다. 단지 보기 편하라고 달아둔 것이니 헷갈리지 않기 바란다.

    여기서는 버블소트에 대한 알고리즘을 익히고자 한 것이 아니라, 배열과 관련된 내용을 많이 배웠으니 실제 사용할 때 어떻게 쓰이는지 익히고자 하는 의도였다. 따라서 알고리즘이 이해되지 않아도 신경쓸 필요가 없는 것이다. 다만 배열을 저렇게 사용할 수 있구나, 하는 것만 알아두기 바란다.

  • 마치는 글

    이번 회에서는 조금 특이한 형태의 인스트럭션도 배웠다. CPU내의 인스트럭션 차원에서 배열을 지원해 준다는 것이 어찌보면 의외였을지도 모르겠다. 또, 이차원 배열의 사용법과 버블소트 예제를 배웠는데, 이렇게 하나하나 배워가는 것이 여러분들의 컴퓨터에 대한 이해에 도움을 주었길 빈다. 다음 회에서는 구조체와 매크로를 배운 후, 링크드리스트를 만들어 간단히 테스트하는 예제도 배울 것이다. 구조체를 직접 어셈블리어로 만들어 보는 것도 매우 흥미롭지 않을까 생각한다.다음 회에서 다시 뵙길 빌며 이만 본회를 마치겠다.

  • "Assembly" 카테고리의 다른 글
    • UNION 사용하기, 매크로란? 매크로 정의하기, 매크... (0)2006/07/10
    • 구조체란? 구조체 선언, 구조체 변수 사용하기 (0)2006/07/10
    • 버블소트 (0)2006/07/10
    • 스트링 비교 예제, 이차원 배열, 베이스-인덱스 디... (0)2006/07/10
    • 스트링관련 인스트럭션들, REP 접두어, 방향 플래... (0)2006/07/10
    2006/07/10 00:45 2006/07/10 00:45
    Posted by webdizen
    No Trackback No Comment

    Trackback URL : http://www.webdizen.net/blog/trackback/1737

    Leave your greetings.

    [로그인][오픈아이디란?]

    Programming/Assembly2006/07/10 00:42

    스트링 비교 예제, 이차원 배열, 베이스-인덱스 디스플레이스먼트

    스트링 비교 예제, 이차원 배열, 베이스-인덱스 디스플레이스먼트

  • 스트링 비교 예제

    간단한 예제를 하나 소개하고자 한다. 두 스트링을 비교하는 예제인데, 반드시 두 스트링의 길이가 같아야 한다. 두 스트링 중 첫번째 것이 작으면 "Source is smaller"라는 문자열을 출력하고, 그렇지 않으면 "Source is not smaller"라는 문자열을 출력하게 된다.

    INCLUDE Irvine32.inc .data source BYTE "INTERNET " dest BYTE "INTERNETCOM" str1 BYTE "Source is smaller", 0dh, 0ah, 0 str2 BYTE "Source is not smaller" 0dh, 0ah, 0 .code main PROC cld mov esi, OFFSET source mov edi, OFFSET dest mov ecx, LENGTHOF source repe cmpsb jb source_smaller mov edx, OFFSET str2 jmp done source_smaller: mov edx, OFFSET str1 done: call WriteString exit main ENDP END main

    대부분 앞에서 설명한 내용이므로 굳이 세세히 설명하지 않아도 될 것 같다. 다만, 비교하다가 중지된 경우 분기를 해준다는 것이 조금 다르다. 공백의 아스키 코드 값 보다 'C'의 아스키 코드 값이 더 크므로 수행시 "Source is smaller"라는 문자열이 출력될 것이다. .data부분에 선언된 것 중 str1과 str2 뒤에 0dh와 0ah는 캐리지리턴과 라인피드로 개행문자이다. WriteString이라는 프로시져를 호출하는 부분이 있는데, 파라미터로 edx에 문자열의 주소를 받는다. 따라서 경우에 따라서 알맞는 스트링의 주소를 edx에 넣어두고 WriteString 프로시져를 호출함으로써 화면에 문자열을 출력할 수 있다. 앞으로도 잘 모르는 프로시져가 나오면 이름과 문맥을 살펴보고 의미를 파악하면 되므로 당황하지 않길 바란다.

  • 나머지 스트링 인스트럭션들

    이제 대충 감을 잡았을 테니 나머지 인스트럭션들은 잡다한 설명을 제외하고 어떻게 쓰는지, 어떤 경우에 사용하면 좋을지를 설명하겠다.

    scasb, scasw, scasd는 scan string의 약자로서 역시 비교를 한다. 하지만 여기서는 esi를 사용하지 않고 al 또는 ax 또는 eax 를 이용하고, 이곳에 있는 값과 edi가 가리키는 곳의 값을 비교하게 된다. 물론 비교 후에는 방향플래그에 따라 edi에 있는 주소값을 증가 또는 감소시킬 것이다.
    이것은 주로 문자열 내에 특정 문자가 있는지 확인할 때, 배열 내에 특정 자료와 일치하는 것이 있는지 확인할 때 편리하게 쓰인다. 특히, 널종료 문자열에서 문자열의 맨 끝으로 이동하려 할 때 유용하게 쓰일 수 있다.

    stosb, stosw, stosd는 store string의 약자로서 자료를 복사하는 역할을 하므로 movs종류와 유사한 일을 한다. 다만 읽어오는 곳이 al 또는 ax 또는 eax이라는 점이 다르다. 여기서도 esi는 쓰이지 않는다. 따라서 al/ax/eax로부터 값을 읽어들여 edi가 가리키는 곳에 쓰게 될 것이다.
    특정 문자로 스트링을 채우려고 할 때 rep접두어와 함께 사용하면 편리할 것이다.

    lodsb, lodsw, lodsd는 load string의 약자로서 자료를 복사하는 역할을 하므로 movs종류와 유사한 일을 한다. 다만 쓰는 곳이 al 또는 ax 또는 eax라는 점이 다르다. 물론 읽어오는 곳은 esi이며, edi를 사용하지 않는다. stos종류와 정 반대의 일을 한다고 생각하면 될 것이다. lods종류는 rep 접두어를 붙여서는 큰 쓸모가 없을 것이다. 왜냐하면 al/ax/eax에 복사되는 자료들이 반복되어봤자 계속해서 덮어 써지기 때문이다. 따라서 이 인스트럭션들은 loop인스트럭션과 함께 사용하는 것이 편리하다.

  • 이차원 배열

    이차원 배열이 무엇인지는 다들 잘 알 것이라 믿는다. 쉽게 말해서 엑셀에 행과 열에 따라 넣은 자료들과 같은 형태라고 생각하면 된다. 그런데 컴퓨터에서 이 이차원 배열을 사용하려면 생각처럼 쉽지 않다. 메모리는 '선형'이기 때문이다. 즉, 메모리에서는 자료를 일렬로 쭉 늘여놓은 형태로 사용한다. 그런데 이것을 마치 행과 열의 평면에서 자료를 다루는 것처럼 사용해야 하니 이것저것 생각할 것이 생기게 되는 것이다. 다음과 같이 자료를 정의해 두었다고 하자.

    .data tableB BYTE 10h, 20h, 30h, 40h, 50h BYTE 60h, 70h, 80h, 90h, 0A0h BYTE 0B0h, 0C0h, 0D0h, 0E0h, 0F0h NumCols = 5

    위와같이 이차원 배열을 정의할 수 있다. 아랫줄의 NumCols는 기호상수로서 이것을 정의한 것 아래에서 NumCols라고 적으면 5로 치환된다. 그렇다면 이차원 배열은 어떻게 사용하면 될까? 다음의 예를 통해서 하나하나 뜯어보자. 그림 1도 참고하면 좀더 이해하기 쉬울 것이다. 아래의 예제는 C에서의 이차원배열로 치자면 tableB[1][2]에 접근하는 예이다.(인덱스는 0부터 시작하는데 주의하라! 일반적으로 행과 열번호에 따라 말하자면 2행 3열이다.)
    RowNumber = 1 ColumnNumber = 2 mov ebx, OFFSET tableB add ebx, NumCols * RowNumber mov esi, ColumnNumber mov al, [ebx + esi]

    < 그림 1 : 이차원 배열>

    먼저 접근하고 싶은 행과 열을 각각 RowNumber와 ColumnNumber에 넣어두었다. 그리고 ebx에 테이블의 시작주소를 넣었고, ebx에 해당 열까지 옮긴 후(add인스트럭션으로) esi에 접근하고 싶은 열의 숫자를 넣어두었다. 그리고 마지막으로 [ebx + esi]에 접근함으로써 tableB[1][2]에 있는 값을 al로 복사하는데 성공하였다. 코드를 수행한 후에 al에는 80h가 들어가 있을 것이다. 그림1을 참고하면 좀 더 이해가 빠르리라 믿는다.

  • 베이스-인덱스 디스플레이스먼트

    이차원 배열을 다루기 위해 쓰는 두번째 방법이다. 만약 이차원 배열의 시작부분이 table이라고 하면, table[ebx + esi]와 같은 식으로 사용하는 방법이다.(table[ebx + esi]는 [table + ebx + esi]와 같은 의미이다. 이 부분이 이해가지 않으면 4회를 다시 보기 바란다. 물론 반드시 ebx와 esi일 필요는 없으니, 그때그때 비어있는 레지스터를 활용하기 바란다.) ebx에는 '행'과 관련된 정보가 있고, esi에는 '열'과 관련된 정보가 들어있을 것이다. 그런데 어떻게 들어있느냐가 궁금할지 모르겠다. 다음의 예제와 그림 2를 참고하면 좀더 이해가 빠를 것이다.

    .data tableB BYTE 10h, 20h, 30h, 40h, 50h BYTE 60h, 70h, 80h, 90h, 0A0h BYTE 0B0h, 0C0h, 0D0h, 0E0h, 0F0h NumCols = 5 .code mov ebx, NumCols mov esi, 2 mov al, tableB[ebx + esi] ; [150 + 5 + 2] = [157]

    < 그림 2 : 베이스-인덱스 디스플레이스먼트>

    이차원 배열을 사용하는 첫번째 방법과 다른 점은, 주소 자체를 갖고 있는 것이 아니라, 오프셋만을 계산한 뒤에 배열에 접근한다는 것이다. 물론 인스트럭션 수는 두번째 것이 좀 더 적지만, 첫번째 것이 좀 더 이해하기는 편할 것이다. 각자 취향대로 필요에 따라 사용하길 권한다.

  • "Assembly" 카테고리의 다른 글
    • 구조체란? 구조체 선언, 구조체 변수 사용하기 (0)2006/07/10
    • 버블소트 (0)2006/07/10
    • 스트링 비교 예제, 이차원 배열, 베이스-인덱스 디... (0)2006/07/10
    • 스트링관련 인스트럭션들, REP 접두어, 방향 플래... (0)2006/07/10
    • 프로시져 호출 규약, LEA 인스트덕션 (0)2006/07/10
    2006/07/10 00:42 2006/07/10 00:42
    Posted by webdizen
    No Trackback No Comment

    Trackback URL : http://www.webdizen.net/blog/trackback/1736

    Leave your greetings.

    [로그인][오픈아이디란?]

    Programming/Assembly2006/07/10 00:41

    스트링관련 인스트럭션들, REP 접두어, 방향 플래그(Direction Flag)

    스트링관련 인스트럭션들, REP 접두어, 방향 플래그(Direction Flag)

  • 시작하기에 앞서...

    이번 회에서는 스트링과 배열을 다룰 때 쓰는 인스트럭션들과 이차원 배열을 사용하는 방법, 문자열 소팅함수를 만드는 방법에 대해 배울 것이다. 또한 본 회의 내용을 이용하면 스트링과 배열 처리를 고급언어를 이용하는 것 보다 훨씬 빠르게 할 수 있다. 어셈블리어에서는 스트링을 다루는 데 이용될 수 있는 좀더 편리한 인스트럭션들이 제공되기 때문이다.(엄밀히 말하면 CPU가 제공하는 것이다.) 이차원 배열은 고급언어에서와 달리 사용하기가 간단하지 않다. 따라서 이를 사용하는 방법을 공부해 볼 것이다. 마지막으로 직접 버블소팅을 이용한 소팅함수를 만들어 볼 계획이다.

  • 스트링관련 인스트럭션들

    스트링 처리와 관련된 인스트럭션들은 다섯가지 '군'으로 분류될 수 있다. 이 다섯가지는 각각 MOVS계열, CMPS계열, SCAS계열, STOS계열, LODS계열 이다. 표 1을 참고하면 각각이 하는 역할을 알 수 있을 것이다. 한가지 알아두어야 할 것은 이들 인스트럭션은 ESI나 EDI를 사용한다는 점이다.

    인스트럭션
    설명
    MOVSB, MOVSW, MOVSD 한 메모리 주소에서 다른곳으로 값을 복사한다.
    CMPSB, CMPSW, CMPSD 메모리에 있는 두 값을 비교한다.
    SCASB, SCASW, SCASD 정수값과 메모리의 값을 비교한다.
    STOSB, STOSW, STOSD 정수값을 메모리에 복사한다.
    LODSB, LODSW, LODSD 메모리의 값을 AL또는 AX 또는 EAX에 읽어들인다.
    < 표 1 : 스트링관련 인스트럭션들>

    스트링 관련 인스트럭션들은 피연산자로 아무것도 받지 않는다. 다만, 사전에 약속해 놓았던 레지스터를 이용하게 될 것이다. 아까 언급했던 esi와 edi는 위의 인스트럭션들이 공통적으로 사용한다. esi에서 s는 source를 뜻하므로 '값을 읽어오는 곳'으로 쓰이고, edi에서 d는 destination을 뜻하므로 '값을 쓰는 곳'으로 쓰인다. 주의할 것은 esi와 edi에 주소가 들어있다는 것이다. esi에서 값을 읽어오는 것이 아니라 esi가 가리키는 곳에서 값을 읽어오고, edi에 값을 쓰는 것이 아니라 edi가 가리키는 곳에 값을 쓴다는 점이다. 따라서 인스트럭션을 수행하기 전에 esi와 edi에 스트링 또는 배열의 시작주소를 넣어둬야 한다.

    위의 표를 보고도 무슨 말인지 잘 모를 수 있다. 뒤에 상세히 설명할 것이니 걱정 말기 바란다. 한가지 궁금한 점이 생길 지 모르겠다. 표 1에 나온 인스트럭션들을 보면 mov인스트럭션과 같이 이전에 배운 것들로도 충분히 할 수 있는 것이기 때문이다. 이에 대한 대답은 rep 접두어(Prefix)에 있다. 다음 단락에서 계속 설명하겠다.

  • REP 접두어

    스트링관련 인스트럭션들은 rep 접두어와 함께 사용될 때 진가를 발휘한다. rep를 '접두어'라 부른 이유는 단독으로 쓰이지 않고 스트링관련 인스트럭션과 결합되어 쓰이기 때문이다. 다음의 표 2에서는 rep, repz, repe, repnz, repne에 대해서 설명하고 있다. repz와 repe는 이름만 다르고 하는 일은 같다. repnz와 repne도 마찬가지이다. 굳이 같은 일을 하는데에 여러 이름이 붙은 것은 단지 코드에서의 가독성을 위한 것이니 신경 쓸 필요는 없을 것이다.

    REP
    ECX > 0 일동안 반복
    REPZ, REPE
    Zero Flag == 0 이고 ECX > 0일동안 반복
    REPNZ, REPNE
    Zero Flag != 0 이고 ECX > 0일동안 반복
    < 표 2 : REP 접두어 >

    접두어를 붙이게 되면 rep 뒤어 적어놓은 인스트럭션을 ecx값 만큼 반복해서 수행한다. 물론 한번 수행할때마다 ecx값을 하나씩 스스로 감소시킬 것이다. 간단한 사용예제는 다음과 같다.

    cld mov esi, OFFSET string1 mov edi, OFFSET string2 mov ecx, 10 rep movsb
    < 예제 1 >

    구체적인 설명은 뒤에서 자세히 할 것이니 여기서는 간단히 설명하겠다. 먼저 cld는 방향 플래그(Direction Flag)를 0으로 해준다. 반대로 std는 방향 플래그를 1로 해준다. 방향 플래그에 대해서는 처음 들어보았을 것이다. 이것 역시 뒤에서 자세히 설명할 것이다. 그 다음 세 줄은 인스트럭션이 의도하는대로 수행될 수 있도록 세팅하는 것이다. 특히 마지막 부분의 ecx에 10을 넣었으니 10번 반복할 것이다. 위와같은 코드를 수행하고 나면 string1이라는 문자열에서 10바이트가 string2로 복사되어있을 것이다. 아직 이해가 안 되었으면 다음 단락의 방향 플래그을 계속 읽어보기 바란다.

  • 방향 플래그(Direction Flag)

    스트링 관련 인스트럭션들은 수행 후에 esi와 edi의 값을 증가시키거나 감소시킨다. esi와 edi에는 포인터를 넣어 두어야 한다고 했다. 따라서 esi와 edi는 바로 다음 것을 가리키게 될 것이다. 하지만 이것은 방향플래그가 0일 때 이야기다. 만약 방향플래그가 1일 경우에는 스트링 관련 인스트럭션 수행 후에 esi와 edi의 값이 감소될 것이다. (스트링 관련 인스트럭션이 b로 끝나는 것이면 1바이트 가감, w로 끝나는 것이면 2바이트 가감, d로 끝나는 것이면 4바이트 가감될 것이다. 각각은 Byte, Word, Double word를 의미한다.) 즉, 배열이나 스트링에서 바로 앞을 가리키게 된다. 다음 표에 요약해 놓았다.

    방향플래그의 값
    ESI와 EDI
    설정 인스트럭션
    0
    증가
    CLD
    1
    감소
    STD
    < 표 3 : 방향 플래그(Direction Flag, DF) >

    이렇게 스트링 관련 인스트럭션에서 값을 가감시키므로 예제 1에서와 같이 rep movsb라고 수행했을 때 계속해서 esi와 edi값이 변하여 복사가 제대로 이루어 질 수 있음을 이해할 수 있을 것이다. 즉, movsb가 한 번 수행 되면 esi가 가리키는 곳에서 1바이트를 읽어 edi가 가리키는 곳에 복사한 뒤 esi와 edi를 하나씩 증가시켜 다음 위치를 가리키게 할 것이다. 만약 movsb가 아니라 movsw 였다면 esi와 edi를 각각 2씩 증가시키고, movsd였다면 esi와 edi를 각각 4씩 증가시켰을 것이다. 그래야만 다음 원소를 올바르게 가리키게 되기 때문이다. 참고로, 예제 1에서는 방향 플래그가 0으로 설정되어있기 때문에 esi, edi가 증가한 것이고, 방향 플래그가 1로 설정되어 있을 경우에는 esi와 edi의 값이 감소하게 되므로 조심하길 바란다.

  • MOVSB, MOVSW, MOVSD 인스트럭션

    movsb, movsw, movsd는 예제 1에 대해서 바로 위에 설명해 놓았으니 무엇을 하는 인스트럭션인지는 감이 왔으리라 믿는다. movs는 move string의 약자이고, 뒤에 붙은 b, w, d는 자료의 크기를 말한다. 이들은 esi가 가리키는 곳의 값을 x바이트 읽어서 edi가 가리키는 곳에 복사한다. x바이트는 movsb일경우 1바이트, movsw일 경우 2바이트, movsd일 경우 4바이트가 될 것이다. 그리고는 방향 플래그의 값에 따라 x바이트 만큼 증가 또는 감소하게 된다. 이것이 잘 이해가지 않을 경우 방향플래그 문단을 다시한번 봐주기 바란다.

  • CMPSB, CMPSW, CMPSD 인스트럭션

    cmps는 compare string의 약자이고 뒤에 붙은 b, w, d는 자료의 크기를 말한다. 무엇의 약자인지를 살펴보면 알겠지만, 이 인스트럭션은 두 자료를 비교하게 된다. 비교해서 각종 플래그들을 세팅할 것이다. 따라서 우리는 비교에 따른 분기를 할 수 있다. 물론 이 인스트럭션을 수행하기 전에도 읽어오는 곳의 주소를 esi에 넣어두고, 쓸 곳의 주소를 edi에 넣어두어야 한다. 다음의 예제를 보면 좀더 이해가 빠를 것이다.

    .data source DWORD 1234h target DWORD 5678h .code mov esi, OFFSET source mov edi, OFFSET target cmpsd ja L1 ; [esi] > [edi]인 경우 jmp L2 ; [esi] <= [edi]인 경우
    오랜만에 점프 인스트럭션이 나왔다. 일단 비교 후 'esi가 가리키는 곳의 값'이 'edi가 가리키는 곳의 값' 보다 클 경우 L1이라는 레이블로 점프를 하게 되고, 그렇지 않을 경우 L2라는 레이블로 점프를 하게 된다. 따라서 두 값의 비교를 통한 분기가 가능한 것이다. 그러나, 단지 두 자료를 비교하는 것만으로 cmpsd를 쓰기엔 너무 긴 코드라는 생각이 들지 않는가?

    방금 들었던 예제는 단지 보여주기 위한 것에 불과하다. 정말 쓸모있게 사용하려면 다음과 같이 사용할 수 있다. (movs종류와 마찬가지로 방향플래그의 값에 따라 esi와 edi가 증가 또는 감소한다는 사실을 잊지 않기 바란다)

    mov esi, OFFSET source mov edi, OFFSET target cld mov ecx, count repe cmpsd
    방향 플래그를 0으로 설정하고 count만큼 cmpsd를 반복하였다. 따라서 순방향으로 증가해가며 비교하되, ecx > 0 이고 비교한 결과가 같을 동안만 반복한다. 따라서 이 예제를 이용하면 문자열이나 배열이 같은지 비교하는 루틴을 만들 수 있을 것이다. 다음 장에서는 좀더 활용적인 예로 설명하겠다.

  • "Assembly" 카테고리의 다른 글
    • 버블소트 (0)2006/07/10
    • 스트링 비교 예제, 이차원 배열, 베이스-인덱스 디... (0)2006/07/10
    • 스트링관련 인스트럭션들, REP 접두어, 방향 플래... (0)2006/07/10
    • 프로시져 호출 규약, LEA 인스트덕션 (0)2006/07/10
    • INVOKE 디렉티브, 스택파라미터를 사용하는 프로시... (0)2006/07/10
    2006/07/10 00:41 2006/07/10 00:41
    Posted by webdizen
    No Trackback No Comment

    Trackback URL : http://www.webdizen.net/blog/trackback/1735

    Leave your greetings.

    [로그인][오픈아이디란?]

    Programming/Assembly2006/07/10 00:40

    프로시져 호출 규약, LEA 인스트덕션

    프로시져 호출 규약, LEA 인스트덕션

  • 프로시져 호출 규약

    매크로 어셈블러는 .MODEL디렉티브를 이용해서 메모리 모델과 모델 옵션을 정할 수 있는데, 모델 옵션으로는 프로시져 호출에 대한 규약을 정할 수 있다. 여러 가지 프로시져 호출 규약 중 stdcall과 cdecl, pascal에 대해 알아보겠다.

    stdcall을 사용할 때는 .model flat, stdcall이라고 소스코드에 적어주면 된다.(flat은 메모리 모델을 이야기한다) stdcall은 파라미터가 넘어갈때 역순으로 넘어간다. 즉,
    INVOKE AddTwo, 5, 6
    이렇게 호출 했을 경우 6이 먼저 스택에 들어가고난 다음 5가 스택에 들어간다. 그리고 함수가 종료될 때, 호출된 함수는 스택에서 파라미터를 제거 시켜줘야 한다. AddTwo함수가 DWORD형 파라미터를 두 개 받는다고 하면
    AddTwo PROC ... ret 8 AddTwo ENDP
    ret인스트럭션 뒤에 숫자 8은 무엇을 의미할까? 함수가 끝나고 리턴될 때, esp에 8을 더하란 뜻이다. (왜 양수냐고 묻기 전에 아래로 자라는 스택임을 상기시키길 바란다) 다시말해서, 스택에 있는 DWORD형(4바이트) 변수 2개를 삭제시키겠다는 뜻이다. 이렇게 함으로서 함수가 호출될 때 스택에 쌓였던 것들이 모두 제거 되었다. 물론 우리가 프로시져를 정의할 때 PROC디렉티브 뒤에 직접 파라미터 리스트를 적은 경우에는 함수 마지막 부분에 그냥 ret라고만 써주면 된다. 뒤에 8을 붙이는 것은 어셈블러가 알아서 해 주기 때문이다.

    cdecl을 사용할 때는 .model C라고 적어주면 된다. cdecl은 파라미터가 스택에 쌓이는 순서는 stdcall과 같다. 하나 다른 점은 함수호출이 끝난 후 스택에 있는 파라미터에 대한 삭제를 호출된 함수가 아니라 그 함수를 호출한 쪽에서 담당한다는 것이다. 즉, 위에서 예로 든 AddTwo를 cdecl으로 작성했다면
    push 6 push 5 call AddTwo add esp, 8
    이렇게 호출 한 다음에 호출했던 쪽에서 스택에 8을 더해 주어야 한다.(stdcall은 호출된 함수 내에서 제거시켜 주었다)

    pascal을 사용할 때는 .model pascal이라고 적어주면 된다. 이는 파라미터를 스택에 넣는 순서가 순방향이다. 즉, stdcall과 반대라는 뜻이다. 그리고 스택에서 파라미터를 누가 지우느냐 하는 것은 stdcall과 같다.

    참고로 MS-Windows 함수는 기본적으로 stdcall을 따른다.

  • LEA 인스트럭션

    지역변수에 대한 포인터는 어떻게 얻어낼까? 우리가 이전에 사용하던 변수들은 대부분 .data에 정의되어 있었고, 이것의 주소는 OFFSET연산자로 알아낼 수 있었다. 이는 메모리의 스태틱 데이터 영역에 있기 때문에 데이터 세그먼트로 부터의 오프셋만 알면 참조할 수 있었다. 또한 그 오프셋은 어셈블할 때 결정되기 때문에 단순히 '연산자'차원에서 가능한 것이다.

    하지만 지역변수나 스택 파라미터는 이야기가 틀려진다. 프로시져는 어디서든 호출될 수 있는데, 그 때마다 스택에 쌓여있는 양이 다르므로 지역변수의 주소는 그때마다 달라지게 된다. 따라서 지역변수의 주소를 얻어오는 인스트럭션이 존재하는데 그것이 바로 lea인스트럭션이다.(Load Effective Address의 약자이다)
    lea (주소를 저장할 곳), (대상)
    이렇게 사용하며 (대상)의 주소를 읽어 (주소를 저장할 곳)에 저장해 준다. 다음에 사용 예가 있다.
    abc PROC USES esi LOCAL string[20]:BYTE lea esi, string ; esi는 배열을 가리키는 포인터가 되었다. ... abc ENDP
    mov esi, OFFSET string 이라고 쓰는 오류를 범하지 않도록 주의해야 한다.

  • 마치는 글

    오늘은 프로시져에 대해서 자세히 배워 보았다. 이제 어셈블리어에서도 고급언어와 같이 프로시져에 파라미터를 넘기고, 지역변수를 만들 수 있게 되었다. 만들 수 있다는 그 자체보다 어떻게 지역변수와 파라미터가 스택에 저장되게 되는지, 어떻게 사라지게 되는지를 아는 것이 이 강좌를 통해 전달하고자 하는 것이다. 다음 회에서는 스트링 처리에 대한 인스트럭션들과 이차원 배열 사용법에 대해 배울 것이다. 필자는 다음 회를 어떻게하면 좀 더 쉽게 설명할 수 있을지 고민하고 있을 테니, 그동안 건강하길 빈다.
  • "Assembly" 카테고리의 다른 글
    • 스트링 비교 예제, 이차원 배열, 베이스-인덱스 디... (0)2006/07/10
    • 스트링관련 인스트럭션들, REP 접두어, 방향 플래... (0)2006/07/10
    • 프로시져 호출 규약, LEA 인스트덕션 (0)2006/07/10
    • INVOKE 디렉티브, 스택파라미터를 사용하는 프로시... (0)2006/07/10
    • LOCAL 디렉티브, 스택파라미터 (0)2006/07/10
    2006/07/10 00:40 2006/07/10 00:40
    Posted by webdizen
    No Trackback No Comment

    Trackback URL : http://www.webdizen.net/blog/trackback/1734

    Leave your greetings.

    [로그인][오픈아이디란?]

    Programming/Assembly2006/07/10 00:37

    INVOKE 디렉티브, 스택파라미터를 사용하는 프로시져의 정의, PROTO 디렉터

    INVOKE 디렉티브, 스택파라미터를 사용하는 프로시져의 정의, PROTO 디렉터

  • INVOKE 디렉티브

    INVOKE는 call 인스트럭션에 스택 파라미터를 넘기는 기능이 추가된 디렉티브이다. 사용방법은 다음과 같다.


    INVOKE 프로시져이름 [인자1, 인자2, ...]

    인자가 없다면 생략 가능하다. 다음의 예제를 보라.

    .data val1 DWORD 12345h val2 DWORD 23456h .code

    진한 글씨로 된 INVOKE 부분은 다음의 코드와 같은 일을 한다.

    push val2 push val1 call AddTwo

    두번째 인자부터 스택에 push되는 것에 유의해야 한다. 그 이유는 프로시져 호출 규약과 관련되어 있으니, 본 회의 뒷쪽에서 설명할 예정이다. 그렇다면 스택 파라미터를 이용하는 프로시져는 어떻게 정의할까?

  • 스택파라미터를 사용하는 프로시져의 정의

    정의하는 방법은 다음과 같다. 일반 프로시져 정의에 파라미터가 추가된 것 뿐이니 어렵게 생각하지 말자.

    프로시져이름 PROC, 파라미터1, 파라미터2, ...... 파라미터n

    정의할때 위와같이 적어주면 된다. 간단한 예를 하나 보자
    AddTwo PROC, val1:DWORD, val2:DWORD ... AddTwo ENDP


    다음은 지역변수까지 있는 프로시져의 정의이다.

    ReadFile PROC, pBuffer:PTR BYTE ;포인터 LOCAL fileHandle:DWORD ... ReadFile ENDP


    여기서 한 가지 주의해야 할 사항이 있다. 바로 위의 예제코드, 즉 ReadFile 프로시져를 보자. 이를 호출할 때 첫번째 파라미터가 포인터이므로 다음과 같이 호출하면 될 것이라 착각하기 쉽다.

    .data myArray BYTE 30 DUP (?) hFile DWORD .code INVOKE ReadFile, OFFSET myArray, hFile


    그러나 위와같이 하면 잘 동작하지 않는다. 프로시져를 INVOKE로 호출할 때, 인자로 변수의 주소를 넘기면 반드시 ADDR연산자를 붙여서 다음과 같이 호출해야 한다.

    INVOKE ReadFile, ADDR myArray, hFile

    이렇게 해야 함수가 잘 동작한다. 이제 스택 파라미터를 이용하는 프로시져를 어떻게 정의해야 할지 감이 왔으리라 믿는다.

  • PROTO 디렉티브

    PROTO 디렉티브는 고급언어의 함수 선언과 같은 역할을 한다. 미리 프로시져의 생김새가 어떠한지 선언해 두는 것이다. 따라서 프로시져의 이름과 파라미터 리스트를 적게 되며, 이를 미리 선언해 두면 그 프로시져를 정의하기 이전에 호출 문장을 사용할 수 있다. 본래 프로시져의 정의에서 PROC을 PROTO로 바꾸고 USES디렉티브가 붙어있다면 제거한 후에, 파라미터 리스트까지만 적으면 된다. 다음 같은과 프로시져가 정의되어있다고 하자.

    ArraySum PROC USES esi ecx, ptrArray:PTR DWORD, szArray:DWORD ... ArraySum ENDP

    이 프로시져의 원형은 다음과 같이 적어주면 된다.

    ArraySum PROTO, ptrArray:PTR DWORD, szArray:DWORD

  • "Assembly" 카테고리의 다른 글
    • 스트링관련 인스트럭션들, REP 접두어, 방향 플래... (0)2006/07/10
    • 프로시져 호출 규약, LEA 인스트덕션 (0)2006/07/10
    • INVOKE 디렉티브, 스택파라미터를 사용하는 프로시... (0)2006/07/10
    • LOCAL 디렉티브, 스택파라미터 (0)2006/07/10
    • 이진수 곱셈, 비트 추출해 내기 (0)2006/07/09
    2006/07/10 00:37 2006/07/10 00:37
    Posted by webdizen
    No Trackback No Comment

    Trackback URL : http://www.webdizen.net/blog/trackback/1733

    Leave your greetings.

    [로그인][오픈아이디란?]

    Programming/Assembly2006/07/10 00:36

    LOCAL 디렉티브, 스택파라미터

    LOCAL 디렉티브, 스택파라미터

  • 시작하기에 앞서...

    5회에서 프로시져에 대해 배운 적이 있다. 그러나 우리가 고급언어에서 사용해 왔던 함수와는 약간 다른점이 있었을 것이다. 지역변수도 없었고, 파라미터도 레지스터를 이용한 방법밖에는 없었다. 이번 회에서는 실제 스택에서 지역변수가 어떻게 생성될 수 있는지, 파라미터는 스택에서 어느 위치에 존재하는지에 대해서 배울 것이다. 따라서 우리는 고급언어에서의 함수와 매우 유사한 형태의 프로시져를 정의할 수 있게 될 것이다.

  • LOCAL 디렉티브

    먼저 지역변수를 선언하는 방법부터 언급하겠다. 이는 LOCAL 디렉티브를 이용해서 사용할 수 있으며 스택에 지역변수에 대한 메모리가 할당된다. 사용 방법은 프로시져의 정의 첫 줄에 다음과 같이 적어주면 된다.
    LOCAL label1:type1, label2:type2, ...
    label은 변수 이름이고, type은 데이터형이다. 배열을 사용하고 싶다면 다음과 같이 선언하면 된다. 다음은 DWORD형의 크기 10을 갖는 배열을 선언한다.

    LOCAL TempArray[10]:DWORD

    LOCAL디렉티브를 사용하면 어셈블러는 이것으로부터 일정한 코드를 생성해 내게 된다. 예를 들어 다음과 같이 프로시져의 정의 내에 LOCAL디렉티브를 사용했다고 하자.

    BubbleSort PROC
    LOCAL temp:DWORD, SwapFlag:BYTE

    ; 함수 안에서 할 일들...

    ret
    BubbleSort ENDP

    위 코드는 어셈블러에 의해 다음과 같이 변환되며, 스택은 그림 1과 같은 모양이 된다.
    BubbleSort PROC
    push ebp ; 이전에 사용해오던 ebp를 저장
    mov ebp, esp ; 지역변수 참조 기준점 설정(ebp)
    add esp, 0FFFFFFF8h ; esp에 -8을 더한다.

    ; 함수 안에서 할 일들...

    mov esp, ebp ; 지역변수 제거
    pop ebp ; 이전에 사용했던 ebp 다시 불러옴
    ret
    BubbleSort ENDP


    < 그림 1 : 함수호출시 스택의 모양>

    그림 1의 스택을 볼 때는 아래로 자라는 스택임을 잊지 않았으면 한다. 또한 그림의 윗쪽으로 갈수록 높은 숫자의 주소를 갖는다. 먼저 위의 코드를 보자. 함수가 호출되면 일단 호출한 곳의 주소가 스택에 쌓일 것이다.(그림1의 return address) 그 다음 이전에 사용중이던 ebp를 스택에 push함으로써 저장시켜놓는다. 그리고 나서 현재 스택의 제일 윗부분(즉 스택의 ebp가 쌓여있는 공간)의 주소를 ebp에 복사한다. 이 레지스터 ebp는 지역변수를 참조하는데 기준이 되는 레지스터이다. 즉, [ebp - 4]와 같은 방법으로 temp변수에 접근할 수 있고, [ebp - 8]과 같은 방법으로 SwapFlag변수에 접근할 수 있다. 그러나 이것은 어셈블리어가 해주는 일이고, 우리는 그저 변수이름을 사용함으로써 그 지역변수에 접근할 수 있다.

    프로시져에서 할 일을 모두 끝냈다면 이제 이전에 했던 초기화 작업을 거꾸로 함으로써 지역변수를 정리하고 이전의 ebp값을 되돌린다. 그림이나 코드에는 나오지 않았지만 ret인스트럭션을 만났을 때 최종적으로 return address까지 스택에서 꺼내어 eip에 값을 복사해 넣었을 것이다.(이는 5회에 잘 나와있다.)

  • 스택 파라미터

    우리가 이전에 5회에서 배웠던 프로시져에서는 레지스터 파라미터를 사용하였다. 즉, 프로시져에 값을 넘길때 레지스터를 이용하였다. 파라미터를 넘기는 또다른 방법은 스택 파라미터를 이용하는 것이다. 이것은 우리가 고급언어에서 사용하던 방법으로, 스택에 파라미터가 쌓여 함수 내에서 사용한 뒤 함수가 리턴되면 파라미터로 사용되었던 변수는 사라지게 된다. 레지스터 파라미터는 상대적으로 빠른 반면에, 자칫 코드가 꼬일 수 있으며 그 개수에 제한이 크다. 스택 파라미터를 이용하면 프로시져 호출 속도는 조금 느려지겠지만, 더 안정적이며 가독성이 높고, 파라미터 개수 제한이 없다. 스택 파라미터도 지역변수와 마찬가지로 프로시져가 호출 된 후 설정되는 ebp값을 기준으로 참조된다. 파라미터에 대해서 표1에 비교해 놓았다.


    pushad

    mov esi, OFFSET array

    mov ecx, LENGTHOF array

    mov ebx, TYPE array

    call DumpMem

    popad

    push TYPE array

    push LENGTHOF array

    push OFFSET array

    call DumpMem


    < 표 1 : (좌)레지스터 파라미터, (우)스택 파라미터>

    표 1의 좌측은 DumpMem이 레지스터 파라미터를 이용하여 작성되었을 때의 호출 방법이고, 표 1의 우측은 스택 파라미터를 이용하여 작성되었을 때의 호출 방법이다.(파라미터의 순서가 뒤바뀐 이유는 뒤에서 설명할 예정이다.) 표 1 좌측과 같이 레지스터 파라미터를 이용한 호출을 안전하게 하려면 pushad와 popad를 이용하여 모든 레지스터를 스택에 저장했다가 불러와야하는 불편함이 있다. 하지만 스택 파라미터를 이용하면 조금더 깔끔하다. 그러나 이것도 한줄에 끝내버릴 수는 없을까? 그 대답은 INVOKE 디렉티브에 있다. 다음과 같이 사용해 보자.
    INVOKE DumpMem, OFFSET array, LENGTHOF array, TYPE array

    어떠한가? 한층 더 간결하면서 보기도 좋지 않은가? 내부적으로 어떤 일을 하는지는 다음문단에서 자세히 설명하겠다.
  • "Assembly" 카테고리의 다른 글
    • 프로시져 호출 규약, LEA 인스트덕션 (0)2006/07/10
    • INVOKE 디렉티브, 스택파라미터를 사용하는 프로시... (0)2006/07/10
    • LOCAL 디렉티브, 스택파라미터 (0)2006/07/10
    • 이진수 곱셈, 비트 추출해 내기 (0)2006/07/09
    • 쉬프트와 로테이트, SHL, SHR, SAL, SAR 인트로덕션 (2)2006/07/09
    2006/07/10 00:36 2006/07/10 00:36
    Posted by webdizen
    No Trackback No Comment

    Trackback URL : http://www.webdizen.net/blog/trackback/1732

    Leave your greetings.

    [로그인][오픈아이디란?]

    «Prev  1 2 3 4  Next»

    RSS HanRSS
    Blog Image
    webdizen
    이 곳은 컴퓨터에 대해 연구하고, 공유하고, 소통하기 위한 연구실입니다. 개인적으로는 OLAP, Data Mining, Semantic Web, Data Modeling에 대해서 연구하고 있습니다.

    Categories

    전체 (2998)
    Webdizen (134)
    Life (6)
    Diary (16)
    Blog (9)
    IDEA (1)
    Travel (10)
    Book (14)
    Photo (7)
    Movie (7)
    Music (13)
    Leisure Sports (10)
    Funny (5)
    Hardware (119)
    Software (120)
    Windows (5)
    Unix & Linux (119)
    Installation (4)
    Kernel (10)
    System (34)
    Develop (22)
    X-Window (0)
    Applicaton (31)
    Security (4)
    Framework (2)
    Hadoop (2)
    Programming (805)
    Algorithm & Data Structure (1)
    Assembly (38)
    UNIX/Linux C (95)
    C++ (128)
    STL (4)
    Java (38)
    Win32 API (92)
    ATL/COM (44)
    MFC (151)
    .NET (26)
    WCF/WPF (4)
    C# (28)
    Network Programming (17)
    Database Programming (12)
    OpenGL / DirectX (13)
    Multimedia Programming (0)
    Game Programming (21)
    Parallel Distributed Progra... (0)
    Reverse Engineering (0)
    Debugging (9)
    Python (1)
    Ruby (1)
    Ruby on Rails (1)
    QT (4)
    GTK (0)
    JSP (0)
    PHP (6)
    ASP.NET (6)
    ASP (3)
    Development (28)
    Useful Library (2)
    Data Modeling (0)
    Database (105)
    Oracle (4)
    MSSQL (41)
    MySQL (2)
    Data Warehouse (2)
    Data Mining (3)
    Network (66)
    Web (78)
    DHTML (4)
    XHTML (1)
    Javascript (1)
    CSS (1)
    AJAX (9)
    XML (11)
    Flex (1)
    Silverlight (3)
    Security (91)
    DoS (1)
    Kernel (10)
    Scanning (3)
    Sniffing (0)
    Spoofing (4)
    Overflow (28)
    Web (11)
    Shell (10)
    Format String (14)
    Window (2)
    Embedded (70)
    Multimedia (27)
    Mobile (14)
    Graphic (24)
    Management (633)
    Knowledge (581)
    Hadoop (0)

    Notice

    • 메타 블로그 사이트에 등록
    • 새해 맞이 블로그의 변화
    • 블로그 명칭 변경
    • 도메인(www.webdizen.net) 구...
    • TEXTCUBE 1.6.1로 업그레이드...

    Tags

    • 친일파
    • FOR XML
    • Hooking
    • XUL
    • Community
    • Sp_OA
    • 프로젝트 관리
    • Network Simulator 2
    • 군집분석
    • 블루 인터네셔날
    • Animation
    • 전자제품
    • CRLF
    • 포스팅
    • Kprobes
    • 패스포드
    • RC0
    • Database
    • Website
    • XSLT

    Recent Articles

    • ASCII Code의 CRLF 제거 방법.
    • Hadoop 에서 c++ API 이용시....
    • Ubuntu Linux에서 Hadoop 구....
    • 내 심장을 한껏 뛰게한 "국가....
    • 스타 스키마 데이터베이스 설....

    Recent Comments

    • ■ 온라인카지노 ▶ http://L....
      asdf 11/21
    • 그리고 혹시 해외여행자보험....
      kim 11/05
    • ★★실제 바다게임장과 똑같....
      asdf 11/04
    • sbsyama.co.to← 짱5000만당....
      asdf 11/04
    • ♡KicaZ??o(???) 바카라사....
      fdsf3fass 11/03

    Recent Trackbacks

    • 파일 열기/저장하기 CFileDialog.
      은마군의 나태블록 02/11
    • World IT Show 2008.
      상우 :: Oranzie's BLOG 2008
    • cvs서버 설치하기.
      3인3색 2008
    • 속속 공개되는 Google Chart....
      PHP와 Web 2.0 2007
    • 마방진을 구하는 프로그램.
      Oranzie's BLOG 3 2007

    Archive

    • 2009/09 (3)
    • 2009/08 (1)
    • 2009/03 (1)
    • 2009/02 (9)
    • 2009/01 (13)

    Calendar

    «   2009/11   »
    일 월 화 수 목 금 토
    1 2 3 4 5 6 7
    8 9 10 11 12 13 14
    15 16 17 18 19 20 21
    22 23 24 25 26 27 28
    29 30          

    Bookmarks

      • Administration
        • IIS.NET
        • NTFAQ
        • OS의 모든 것
        • 리눅스포털
      • Database
        • SQL Server Central
        • SQL Team
      • Development
        • .NET Heaven
        • ASP Alliance
        • ASP.NET 2.0
        • Bullog.net
        • C# Corner
        • C++ (C PlusPlus.com)
        • C++ Reference
        • CodeGuru
        • CodePlex
        • DebugLab
        • Dev Articles
        • Devpia
        • DotNet Junkies
        • DotNet Zone
        • Driver Online
        • GOSU.NET
        • HOONS 닷넷
        • Joinc 팀블로그
        • KOSR
        • MSDN Home Page
        • OSR Online
        • Sky.ph - 개발자 커뮤니...
        • TAEYO.NET
        • The Code Project
        • WindowsClient.net
        • 김상욱의 개발자 Side
        • 조인시 위키
      • Human Networks
        • belief21c's e-space
        • I think I can
        • Invisible Rover's Blog :D
        • Rodman®
        • ■ Feel So Good~! ■
        • 까만 나비
        • 나를 가꾸는 시간.
        • 나만의 즐거움~~!
        • 단녕
        • 상우 :: Oranzie's BLOG
      • Information Technology
        • Microsoft TechNet
        • 지디넷코리아 - 글로벌...
      • Security
        • FoundStone
        • milw0rm
        • NewOrder
        • OpenRCE
        • Phrack.org
        • Reverse Engineering b1...
        • Reverse Engineering Team
        • RootKit
        • SecurityFocus
        • SecurityXploded by Nag...
        • Wow Hacker
        • Zone-H
    Textcube
    Louice Studio Inc.
    Powered by Textcube. Original designed by Tistory.