블로그 이미지
하루, 글. 그림. 영상매체. 표현을 도와주는 기기들. 도전 중. 동화다아아
    동화다아아

    카테고리

    분류 전체보기 (176)
    잡담 (1)
    IT 기기-리뷰&뉴스 (7)
    리뷰 - 도서 (1)
    리뷰 - 영상 (0)
    리뷰 - 그림/음악 (1)
    내장형 하드웨어 (163)
    Total
    Today
    Yesterday

    test(4,3);

    ⇒ push 3

       push 4

       call test(→push eip, → call test)


     

    printf

     

     

    test

     

    main stack ebp(old ebp)

    함수 호출 시 반드시 필요한 영역(overhead)

    ret

    4

    3

    main

     

     

     

    ← esp: main

     

     

    B

     

    A

     

    stack ebp

    RET(retrurn address)

     

    init

    ← ebp: main

     

     

     

    - disassemble

     test

     return

     push ebp

     mov ebp, esp

     sub esp, 50h

     mov esp, ebp

     pop ebp

     ret

     → test의 세 개의 코드를 entry code라 한다.

     → return의 세 개의 코드를 exit code라 한다.

     → 처음에 C에서 우리가 변수를 몰아 선언하듯이 esp도 메모리를 미리 일정부분 확보한 다. (sub esp, 50h)


    ※ stack 호출시 최소한 8byte의 메모리가 필요하다. 인자 2개가 4byte를 차지하는 것 이외에도 ret, old ebp가 들어가기 때문에

     → 즉, 함수를 너무 많이 호출하면 좋지 않다. 함수 호출을 통하여 2개의 인자(push 3, push 4) 이외에도 call test의 두가지 일(push eip, call test)가 발생하게 되기 때문.

     → ARM 칩의 경우에는 인자를 4개까지는 레지스터에 저장하므로 4개까지는 굉장히 빠르게 되지만 5개 부터는 메모리를 사용해야 하므로 속도가 급격히 느려진다.

     → 즉, stack 구조에서 인자는 없는게 사실상 가장 빠르다. 그러므로 최적화를 위해서는 인자의 개수를 너무 많이 사용하는 것은 조심 한다.


    MASM 컴파일.

    ⇒ 컴파일 방법

    1. 컴파일

    ml /c /coff masm.asm

    → ml:microsoft assembler

    → /c 컴파일해라

    → /coff 공통 obj 파일을 생성해라

    → 실행파일


    2. 링킹

    link /subsystem:console /entry:embedded /out:실행파일.exe 실행파일.obj io.obj kernel32.lib

    → /subsystem:console(도스창에서 이기 때문에 console을 붙인다.)

    → /entry:embedded 함수가 시작점

    → /out: 최종적으로 만들어 내는 실행파일(.exe)

    → link 시킬 파일을 적는다.(실행파일.obj io.obj kernel32.lib)


    3. 실행

    실행파일.exe


    ※ C:\jbpup\Detmer에서

    io.h io.obj kernel32.lib link.exe 를 복사해서 컴파일할 폴더에 붙이면 해당 폴더에서 컴파일 가능


     

    .386 ; 386이상 호환, ‘.’은 특정 모델 명기.

    .MODEL FLAT ; FLAT 메모리 방식.


    ExitProcess PROTO NEAR32 stdcall, dxExitCode:DWORD

    ; ExitProcess → 기본으로 제공하는 함수.

    ; protov 선언.

    ; near32 → 32bit에 가깝다.

    ; stdcall → push 방법.

    ; dxExitCode:DWORD → 반환값이 4byte이다.


    INCLUDE io.h

    ; C와 같은 역활

    cr    EQU    0dh ; cr EQU(equal) 0DH(→ hexa)

                    ;  #define cr 0x0D와 같다.(cr을 프로그램에서 0x0D로 대체한다.)

    Lf    EQU    0ah ; 0A와 위의 0D는 아스키 코드를 뜻한다.


    .STACK 4096 ; stack을 4096만큼 선언하겠다.(stack을 1024칸 사용가능 하도록 확보하겠다. ※C에서는 자동으로 해주지만 어셈블리에서는 직접 해주어야 한다.)


    .DATA ; 전역변수(어셈블리에서 전역변수를 선언했다.)

    number1    DWORD    ? ; 변수 이름, DWORD는 double word이므로 4byte

    number2    DWORD    ? ; ? 는 쓰레기값을 뜻한다.

    prompt1    BYTE      "Enter first      number :     ", 0 ; 1byte이며 “” 내부는 배열이 선언되어있다. 즉, 각 글자가(띄어쓰기 포함) 1byte씩의 크기를 가진다. ,0(Null)은 문자열에서의 Null과 같다. 어셈블리는 자동으로 문자열에 Null이 들어가지 않으므로 적어주어야 한다.

    →  “kkk”라는 문자열이 있다면 C는 4byte 어셈블리는 3byte이다. C는 Null을 자동으로 포함하기 때문이다.

    prompt2    BYTE      "Enter second number :     ", 0

    string     BYTE      40    DUP  (?) ; C에서 char string[40];과 같다. 즉, 초기화 안된 string을 넣었으므로 쓰레기값 ‘?’ 상태이다. DUP - 40에 ?를 복사해 넣어라. 즉, 40byte에 쓰레기값이 복사된다.

    label1     BYTE      cr,    Lf,     "The Sum is " ; C에서 "\r\rthe sum is"인데 어셈블리에서 개행문자를 지원하지 않으므로 cr, lt를 이용한다. 줄을 바꾼다.

    sum        BYTE      11    DUP  (?) ; FFFFFFFF가 10진수 열자리이므로 그 이상의 값을 주었다.

               BYTE      cr,    Lf,     0 ; 여기까지 변수(지역)가 총 7개

           

    .CODE ; 코드영역의 시작을 선언

    _embedded: ; 어셈블리 외부에서 쓰는 명령은 _(언더바)를 붙인다.

                ; 함수의 시작을 알린다.(임베디드 함수가 여기서 시작한다.-함수의 본체)

            output   prompt1 ; 어셈블리 문법이 아니다.(메크로), 뒤에것을 출력해준다.(표준이 아니며 교육용으로 선언된 것. printf와 비슷하다.)

            input    string, 40 ; 입력을 받는다. 문자열을 40 글자만큼 입력받을 수 있다.

            atod     string ; ASCII to decimal - 아스키를 10진수로 바꾼다. 그리고 eax라는 레지스터에 저장한다.(atod역시 메크로)

            mov      number1, eax ; eax의 값을 number1에 집어넣어라. mov는 뒤에서 앞으로 대입하라.(assembly 에서는 전송이라는 뜻)

            

            output   prompt2

            input    string, 40

            atod     string

            mov      number2, eax

           

            mov      eax, number1

            add      eax, number2 ; add - 덧셈하다. C로 표현하면 eax = eax+number2;와 같다. 즉, number1+number2를 eax에 넣는 것.

            dtoa     sum, eax ; decimal to ASCII 10진수를 아스키로 바꾼다.

            output   label1 ;

           

            INVOKE   ExitProcess, 0

           

    PUBLIC  _embedded ; 위와 현재의 embedded는 C의 { }와 같다.

     

    END ; 전체 소스가 끝났다는 뜻.




    - 실습 (Hello world!!)

    .386

    .MODEL FLAT


    ExitProcess PROTO NEAR32 stdcall, dxExitCode:DWORD


    INCLUDE io.h


    cr    EQU    0dh

    Lf    EQU    0ah


    .STACK 4096


    .DATA

    prompt1    BYTE      "Hello world!!", 0 ; 전역변수

                                             ; 어셈블리어 코드 주석은 ;(세미콜론)이다.

                                            ; 어셈블리는 “” 내의 문자에서 C처럼 null을 자동으로 첨부하지 않기 때문에 ,0을 표시해 주어야 한다.


           

    .CODE

    _embedded: ; 엔트리 포인트

            output   prompt1 ; output은 실제 어셈블리에 있는게 아니라 메크로로 만들어 둔 것이다. intput도 마찬가지. 이해를 돕기 위한 것으로 실재로는 printf와 scanf를 뜻한다.

            INVOKE   ExitProcess, 0 ; INVOKE는 exit 함수를 뜻하는 것으로써 어디서든 exit를 호출하게 되면 강제로 종료시키게 된다.

           

    PUBLIC  _embedded


    END


    Posted by 동화다아아
    , |

    최근에 달린 댓글

    최근에 받은 트랙백

    글 보관함