ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 시스템프로그래밍 02 - 어셈블리어 들어가기
    쾌락없는 책임 (공부)/시스템프로그래밍 2021. 4. 18. 20:08
    반응형

    본 포스트는 강동완 교수님의 '시스템프로그래밍' 강의를 듣고

    이해한 것들을 정리한 포스트입니다.

    - 강의자료는 올리지 않습니다


    <I/O>

    컴퓨터에서 입출력은 4단계(교수님은 3단계라 하셨는데 0~3이라 3단계인것 같습니다)를 가지고 있으며 각 레벨은 아래와 같습니다.

    고수준 언어의 레벨 C, C++ 또는 그 이상 수준의 언어로 작성된 함수로 입출력을 제어하는 것.
    OS나 시스템에 의존적이지 않고 범용성이 아주 뛰어납니다.
    대신 그만큼 하드웨어 제어권이 떨어지게 됩니다.
    운영체제 레벨 운영체제의 라이브러리를 이용하는 것으로 키보드 문자열 입력 등등의 작업이 해당됩니다.
    BIOS 레벨 운영체제는 BIOS와 소통을 하는데 BIOS 레벨에서 작성된 입출력 제어는 하드웨어에 직접 접근이 가능합니다.
    대신 같은 BIOS에서만 작동될 정도로 범용성이 떨어지게 됩니다.
    하드웨어 레벨 장치 드라이버가 예시

     이건 각 언어들의 특성과도 같습니다. C에 가까울수록 하드웨어, 메모리 관리가 좋으나 어렵고 파이썬에 가까울수록 메모리 관리는 떨어지는 것 같은데 사용하기는 편하고...

     

     앞으로 배우는 어셈블리어는 CPU의 레지스터를 이용하는 등 하드웨어 권한이 정말 뛰어납니다! 대신 프로세서마다, 어셈블리어 만든 회사마다 다르기 때문에 일단 강의에서는 대표적인 어셈블리어중 하나인 '마이크로소프트'의 어셈블리어를 이용합니다. (MASM)

     

     

     

    <기초 어셈블리어>

    기존 고급 언어에서 수를 더하는 작업은  a+b 같은 형식으로 했지만 어셈블리어에서는 각 수들을 '메모리에 할당'하고 그 할당된 메모리를 통해서 결과값을 찾아내야 합니다.

    main PROC
    	mov eax, a
        add eax, b
        
        INVOKE ExitProcess, 0 ; 종료
    main ENDP

     mov 들여쓰기가 이상하긴 하지만... 그리고 위처럼 a,b 를 쓰지는 않고 a=6, b=7이라면 6, 7 이런식으로 써줘야 합니다.

     위 코드는 먼저 a를 eax 레지스터로 이동시킵니다. 그럼 eax레지스터에는 a가 이을 것이고 이곳에 b 를 더해 a+b가 eax레지스터에 저장되게 됩니다. 이런 식입니다.

     

    어셈블리어 기초 문법

    1. 정수 표현하기

    (부호 +, -) 숫자 (몇진수?)

        - 위 부호는 선택사항이며 디폴트는 + 입니다mov같은 명령어, 

        - (몇진수?) 의 경우 2,8,10,16 진수중 무슨 진수인지 입력하는 곳이고 디폴트는 10진수입니다.

     

     위 문법은 숫자 자체를 나타내는 방법이며 이걸 할당하거나 변수명을 주는건 이후 배우게 됩니다. 또한 주의사항으로는 16진수를 표기할 때 정수가 알파벳(10진수에서 10이상의 값)으로 시작한다면 앞에 0을 붙이고 시작해야 한다는 것입니다.   (예시 : 0FFh)

     

    2. 실수 표현하기

    (부호 +, -) 숫자.(숫자) (몇진수?)    ; Decimal Real

     실수 표현에는 위와 같은 Decimal 방식이 있고 Encoded방식이 있는데 Encoded방식은 잘 사용하지 않는다고 합니다.

     (Encoded : 16진수로 표현하며 부호, 정수, 소수 부분이 비트별로 나뉘어 있습니다.)

     

    3. 문자 / 문자열

     다행히도 'A'나 "A"이런 식으로 치면 문자 입력을 받아줍니다. 대신 실제로는 아스키코드로 받아준다는거.

     문자열의 경우 'ABCD'같이 선언하면 되지만 실제로는 배열처럼 저장되기 때문에 문자 하나하나 순차적으로 메모리에 저장됩니다.

     

     

    4. 예약어

     위에서 사용한 mov가 예시이며 이런 예약어는 대소문자 구별을 하지 않습니다. 즉, mov든 MOV든 같다는 이야기. 종류에는 mov같은 명령어, 레지스터 이름, 지시어, Attributes(DWORD같은 데이터 크기를 지정하는 것들), 연산자 등이 있습니다.

     

    5. 식별자

     프로그래머가 직접 지정한 변수나 상수의 이름으로 만드는 규칙은 다른 언어들과 같게 예약어와 겹칠 수 없고 문자, _, @, $, ?, 숫자를 사용할 수 있지만 시작이 숫자가 되어서는 안됩니다.

     

    6. Directives (지시어)

     Directive들은 어셈블러에 의해 인식되는 것들로 어셈블러에 명령을 내린다고 생각하면 됩니다(변수이름 등). 프로세스마다 Directive가 다르기도 하며 이것들도 대소문자를 가리지 않습니다.

     

    7. Instructions

     이것들은 특이하게도 실행시 어셈블러가 어셈블시 실행 가능한 명령어로 교체해줍니다. 때문에 실행 속도와는 아무런 연관이 없습니다. 종류는 총 4가지가 있습니다.

    (Label) mnemonic (Operands) (;주석)

    7-1. Label

     - 사실상 Directive라고 생각하면 편합니다. (이것 자체가 Instructions는 아니고 함께 쓰인다는 정도)

     - 종류는 데이터 레이블과 코드 레이블 2가지가 있습니다.

          - 데이터 레이블 : 변수의 메모리상 위치를 암시

          - 코드 레이블 : Instruction의 메모리상 위치를 암시

     - 한마디로 '변수선언'과 비슷하다고 할 수 있으며 이 레이블을 통해서 어셈블러가 이 값의 메모리상 위치를 알게 됩니다. (인덱스같은 역할)

    number WORD 10    ; number이 Label (Data Lable)

    * 한 Label에 여러 값들을 넣을 수 있습니다  : number WORD 10, 20, 30...

     

    L1 : mov a1, b1      ; Code 레이블에서는 : 을 붙여야 합니다.

    * C에서 switch문과 비슷, 명령어들의 위치를 가리켜 줍니다

    * 레이블은 '메모리의 주소값'을 가리킨다고 생각하기!

    7-2. Mnemonic

     - 앞서 본 mov같은 애들이 이에 해당

    7-3. Operands

     - 피연산자로 사실상 선택이 아닌 대부분의 경우에서 사용되게 됩니다.

     

    * 피연산자가 없는 것 (NOP)

     예시 :     (offset) 90       nop

     - 1바이트로 아무 일도 하지 않는다. 이걸 사용하는 이유는 32비트에서 버스 크기가 4바이트라 4의 배수로 맞춰야 접근이 쉽습니다. 그래서 이를 쉽게 해주기 위해 nop를 사용해 4의 배수로 맞춰주게 됩니다.   (이건 프로그래머가 코드 짤 때 잘 생각해야 한다)

     

     

    어셈블리어 실행

     이런 어셈블리어를 비주얼스튜디오를 통해 실행할 수 있다! (물론 해보진 않았다) 하고 나면 어셈블리어가 기계어로 번역된 중간 파일이 나오며 여기서 맨 앞 offset값이 보이게 된다. offset은 이 명령이 메모리의 어느 위치에서 시작하는지 알려주는 값이다.

    반응형

    댓글

Designed by Tistory.