Language/Assembly ASSEMBLY 기초/문법
  • 728x90
    반응형



    Assmbly





    asm_io.inc


    asm_io.asm


    80x86_assembly.zip


    첨부파일에는 컴파일 링크시 필요한 asm_io.inc, asm_io.asm 파일과 nasm 컴파일러 올려둡니다.


    nasm 컴파일은 아래와 같은 경로에서 받을수 있다.

      




    nasm 컴파일


    Ex) asm_io.asm 파일 내부

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    418
    419
    420
    421
    422
    423
    424
    425
    426
    427
    428
    429
    430
    431
    %define NL 10
    %define CF_MASK 00000001h
    %define PF_MASK 00000004h
    %define AF_MASK 00000010h
    %define ZF_MASK 00000040h
    %define SF_MASK 00000080h
    %define DF_MASK 00000400h
    %define OF_MASK 00000800h
     
    %ifdef ELF_TYPE
      %define _scanf   scanf
      %define _printf  printf
      %define _getchar getchar
      %define _putchar putchar
      %define _fputs   fputs
    %endif
     
    %ifdef OBJ_TYPE
    segment .data public align=class=data use32
    %else
    segment .data
    %endif
     
    int_format    db  "%i"0
    string_format       db  "%s"0
    reg_format    db  "Register Dump # %d", NL
       db  "EAX = %.8X EBX = %.8X ECX = %.8X EDX = %.8X", NL
                        db  "ESI = %.8X EDI = %.8X EBP = %.8X ESP = %.8X", NL
                        db  "EIP = %.8X FLAGS = %.4X %s %s %s %s %s %s %s", NL
               db  0
    carry_flag    db  "CF"0
    zero_flag    db  "ZF"0
    sign_flag    db  "SF"0
    parity_flag    db "PF"0
    overflow_flag    db "OF"0
    dir_flag    db "DF"0
    aux_carry_flag    db "AF"0
    unset_flag    db "  "0
    mem_format1         db  "Memory Dump # %d Address = %.8X", NL, 0
    mem_format2         db  "%.8X "0
    mem_format3         db  "%.2X "0
    stack_format        db  "Stack Dump # %d", NL
               db  "EBP = %.8X ESP = %.8X", NL, 0
    stack_line_format   db  "%+4d  %.8X  %.8X", NL, 0
    math_format1        db  "Math Coprocessor Dump # %d Control Word = %.4X"
                        db  " Status Word = %.4X", NL, 0
    valid_st_format     db  "ST%d: %.10g", NL, 0
    invalid_st_format   db  "ST%d: Invalid ST", NL, 0
    empty_st_format     db  "ST%d: Empty", NL, 0
     
    %ifdef OBJ_TYPE
    segment text public align=class=code use32
    %else
    segment .text
    %endif
    global read_int, print_int, print_string, read_char
    global  print_char, print_nl, sub_dump_regs, sub_dump_mem
            global  sub_dump_math, sub_dump_stack
            extern  _scanf, _printf, _getchar, _putchar, _fputs
     
    read_int:
    enter 4,0
    pusha
    pushf
     
    lea eax, [ebp-4]
    push eax
    push dword int_format
    call _scanf
    pop ecx
    pop ecx
    popf
    popa
    mov eax, [ebp-4]
    leave
    ret
     
    print_int:
    enter 0,0
    pusha
    pushf
     
    push eax
    push dword int_format
    call _printf
    pop ecx
    pop ecx
     
    popf
    popa
    leave
    ret
     
    print_string:
    enter 0,0
    pusha
    pushf
     
    push eax
    push    dword string_format
    call _printf
    pop ecx
    pop ecx
     
    popf
    popa
    leave
    ret
     
    read_char:
    enter 4,0
    pusha
    pushf
     
    call _getchar
    mov [ebp-4], eax
     
    popf
    popa
    mov eax, [ebp-4]
    leave
    ret
     
    print_char:
    enter 0,0
    pusha
    pushf
     
    push eax
    call _putchar
    pop ecx
     
    popf
    popa
    leave
    ret
     
     
    print_nl:
    enter 0,0
    pusha
    pushf
     
    push dword 10
    call _putchar
    pop ecx
     
    popf
    popa
    leave
    ret
     
     
    sub_dump_regs:
    enter   4,0
    pusha
    pushf
    mov     eax, [esp]
    mov [ebp-4], eax
     
    test eax, CF_MASK
    jz cf_off
    mov eax, carry_flag
    jmp short push_cf
    cf_off:
    mov eax, unset_flag
    push_cf:
    push eax
     
    test dword [ebp-4], PF_MASK
    jz pf_off
    mov eax, parity_flag
    jmp short push_pf
    pf_off:
    mov eax, unset_flag
    push_pf:
    push eax
     
    test dword [ebp-4], AF_MASK
    jz af_off
    mov eax, aux_carry_flag
    jmp short push_af
    af_off:
    mov eax, unset_flag
    push_af:
    push eax
     
    test dword [ebp-4], ZF_MASK
    jz zf_off
    mov eax, zero_flag
    jmp short push_zf
    zf_off:
    mov eax, unset_flag
    push_zf:
    push eax
     
    test dword [ebp-4], SF_MASK
    jz sf_off
    mov eax, sign_flag
    jmp short push_sf
    sf_off:
    mov eax, unset_flag
    push_sf:
    push eax
     
    test dword [ebp-4], DF_MASK
    jz df_off
    mov eax, dir_flag
    jmp short push_df
    df_off:
    mov eax, unset_flag
    push_df:
    push eax
     
    test dword [ebp-4], OF_MASK
    jz of_off
    mov eax, overflow_flag
    jmp short push_of
    of_off:
    mov eax, unset_flag
    push_of:
    push eax
     
    push    dword [ebp-4]
    mov eax, [ebp+4]
    sub eax, 10
    push eax
    lea     eax, [ebp+12]
    push    eax
    push    dword [ebp]
            push    edi
            push    esi
    push    edx
    push ecx
    push ebx
    push dword [ebp-8]
    push dword [ebp+8]
    push dword reg_format
    call _printf
    add esp, 76
    popf
    popa
    leave
    ret     4
     
    sub_dump_stack:
    enter   0,0
    pusha
    pushf
     
    lea     eax, [ebp+20]
    push    eax
    push    dword [ebp]
    push dword [ebp+8]
    push dword stack_format
    call _printf
    add esp, 16
     
    mov ebx, [ebp]
    mov eax, [ebp+16]
    shl eax, 2
    add ebx, eax
    mov edx, [ebp+16]
    mov ecx, edx
    add ecx, [ebp+12]
    inc ecx
     
    stack_line_loop:
    push edx
    push ecx
     
    push dword [ebx]
    push ebx
    mov eax, edx
    sal eax, 2
    push eax
    push dword stack_line_format
    call _printf
    add esp, 16
     
    pop ecx
    pop edx
     
    sub ebx, 4
    dec edx
    loop stack_line_loop
     
    popf
    popa
    leave
    ret     12
     
     
    sub_dump_mem:
    enter 0,0
    pusha
    pushf
     
    push dword [ebp+12]
    push dword [ebp+16]
    push dword mem_format1
    call _printf
    add esp, 12 
    mov esi, [ebp+12]
    and esi, 0FFFFFFF0h
    mov ecx, [ebp+8]
    inc ecx
    mem_outer_loop:
    push ecx
    push esi
    push dword mem_format2
    call _printf
    add esp, 8
     
    xor ebx, ebx
    mem_hex_loop:
    xor eax, eax
    mov al, [esi + ebx]
    push eax
    push dword mem_format3
    call _printf
    add esp, 8
    inc ebx
    cmp ebx, 16
    jl mem_hex_loop
    mov eax, '"'
    call print_char
    xor ebx, ebx
    mem_char_loop:
    xor eax, eax
    mov al, [esi+ebx]
    cmp al, 32
    jl non_printable
    cmp al, 126
    jg non_printable
    jmp short mem_char_loop_continue
    non_printable:
    mov eax, '?'
    mem_char_loop_continue:
    call print_char
     
    inc ebx
    cmp ebx, 16
    jl mem_char_loop
     
    mov eax, '"'
    call print_char
    call print_nl
     
    add esi, 16
    pop ecx
    loop mem_outer_loop
     
    popf
    popa
    leave
    ret 12
     
    sub_dump_math:
    enter 116,0
    pusha
    pushf
     
    fsave [ebp-108]
    mov eax, [ebp-104]
    and eax, 0FFFFh
    push eax
    mov eax, [ebp-108]
    and eax, 0FFFFh
    push eax
    push dword [ebp+8]
    push dword math_format1
    call _printf
    add esp, 16
     
    mov cx, [ebp-104]
    shr cx, 11
    and cx, 7
    mov bx, [ebp-100]
    shl     cl,1
    ror bx, cl
     
    mov edi, 0
    lea esi, [ebp-80]
    mov ecx, 8
    tag_loop:
    push ecx
    mov ax, 3
    and ax, bx
    or ax, ax
    je valid_st
    cmp ax, 1
    je zero_st
    cmp ax, 2
    je invalid_st
    push edi
    push dword empty_st_format
    call _printf
    add esp, 8
    jmp short cont_tag_loop
    zero_st:
    fldz
    jmp short print_real
    valid_st:
    fld tword [esi]
    print_real:
    fstp qword [ebp-116]
    push dword [ebp-112]
    push dword [ebp-116]
    push edi
    push dword valid_st_format
    call _printf
    add esp, 16
    jmp short cont_tag_loop
    invalid_st:
    push edi
    push dword invalid_st_format
    call _printf
    add esp, 8
    cont_tag_loop:
    ror bx, 2
    inc edi
    add esi, 10
    pop ecx
    loop    tag_loop
     
    frstor [ebp-108]
    popf
    popa
    leave
    ret 4
    cs

     


    위 파일을 컴파일하여 obj 파일을 생성 할 수 있다.

      

     

     

    Ex) first.asm 파일 내부

    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    %include "asm_io.inc"
     
    segment  .data
     
    prompt1 db  "Enter a number: ",0
    prompt2 db  "Enter another number: ",0
    outmsg1 db  "You entered ",0
    outmsg2 db  " and ",0
    outmsg3 db  ", the sum of these is ",0
     
    segment  .bss
     
    input1  resd 1
    input2  resd 1
     
    segment  .text
      global  _asm_main
    _asm_main:
      enter  0,0
      pusha
      
      mov  eax,prompt1
      call  print_string
      
      call  read_int
      mov    [input1], eax
      
      mov    eax,prompt2
      call  print_string
      
      call  read_int
      mov    [input2], eax
      
      mov    eax, [input1]
      add    eax, [input2]
      mov    ebx, eax
      
      dump_regs  1
      dump_mem  2,  outmsg1,  1
      
      mov    eax, outmsg1
      call  print_string
      mov    eax, [input1]
      call  print_int
      mov    eax, outmsg2
      call  print_string
      mov    eax, [input2]
      call  print_int
      mov    eax, outmsg3
      call  print_string
      mov    eax, ebx
      call  print_int
      call  print_nl
      
      popa
      mov    eax, 0
      leave
      ret
     
    cs

      

     

    위와 동일한 방법으로 obj 파일 생성 

     

    Ex) print 종류의 함수를 사용하기위한 asm_io.inc

    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
    extern  read_int, print_int, print_string
    extern read_char, print_char, print_nl
    extern  sub_dump_regs, sub_dump_mem, sub_dump_math, sub_dump_stack
     
    %macro dump_regs 1
    push  dword %1
    call  sub_dump_regs
    %endmacro
     
    %macro  dump_mem 3
    push dword %1
    push dword %2
    push dword %3
    call sub_dump_mem
    %endmacro
     
    %macro dump_math 1
    push dword %1
    call sub_dump_math
    %endmacro
     
    %macro  dump_stack 3
    push dword %3
            push     dword %2
    push dword %1
            call     sub_dump_stack
    %
    cs

      

    Ex) drive.c 파일 내부


    위와 동일한 방법으로 obj 파일 생성 

     

    아래와 같이 3개의 obj 파일을 LINK 하면 EXE 파일이 생성된다.



    < 실행 결과 > 




    ASSEMBLY LANGUAGE 


     

    주석


    C :    //, /* */

    asm :    ;


      

    대입

     

    C :    dest = src;

    asm :    mov    dest, src



    덧셈

    C :    eax = eax + 4;

    asm :    add    eax, 4


    C :    al = al + ah

    asm :    add    al, ah



      

    뺄셈

    C :    bx = bx - 10;

    asm :    sub    bx, 10

     

    C :    ebx = ebx - edi;

    asm :    sub    ebx, edi


      

    증가, 증감 연산자


    C :    ecx++;

    asm :    inc    ecx

     

    C :    dl--;

    asm :    dec    dl

     

      

    전처리 방법


    C :     #define    PI    3.14

    asm :    %define    equ    3.14

     


    변수 선언

    ( 어셈블리는 변수가 아닌 주소로 접근 하기 때문에 void 포인터라 본다 )

     


    C :    char    L1 = 0;

    asm :    L1    db     0 



        L3    db    110101b 

        ※ 어셈블리는 초기화의 b 를 붙여 2진수로 초기화가 가능하다. 


        L4    db    12h 

        ※ 어셈블리는 초기화의 h 를 붙여 16진수로 초기화가 가능하다. 


        L6    dd    1A92h 

        ※ double word(4byte) 형으로 16진수로 초기화 되었다. 


        L7    resb    1 

        ※ resb 는 배열과 같은 긴데이터를 생성하는데 res 는 값을 넣지 않는다는 뜻이다. 


        L8    db    "A" 

        ※ 1byte 크기의 A의 아스키 코드를 초기화 


        L9    0, 1, 2, 3 

        ※ 1byte 크기의 4개의 초기화 총 4byte 


        L10    "w", "o", "r", 'd', 0 

        ※ 5byte 크기의 C의 문자열 "word" 와 유사하며 마지막의 NULL은 셀프로 항상 넣어 주어야 한다.

        ※ (" "), (' ') 둘다 사용가능 


    Unit 

    Letter 

    byte

    B (1byte)

    word

    W (2byte)

    double word

    D (4byte)

    quad word

    ten bytes

     

        L12    times    100 db    0

        ※ db 크기의 0을 100번 반복 


        L13    resw    100 

        ※ 초기화가 안된 200byte 크기를 뜻함 


        mov    al, [L1] 

        ※ 대괄호를 쳐야 L1의 값을 al에 대입한다. 


        mov    eax,    L1 

        ※ eax 는 4byte크기의 레지스터이며 대괄호가 없으면 L1의 주소값이 대입된다. 


        mov     [L1], ah 

        ※ ah 값을 L1의 주소에 대입. 


        mov    [L6], 1 

        ※ L6 의 주소에 1을 넣는다.

        ※ 위의 방법은 1의 크기를 컴파일이 알지 못한다. 아래의 방법으로 해결한다. 


        mov    dword    [L6], 1 


    C언어는 컴파일러가 형동등성에 의해 대입시에 편의를 봐준다. 


    어셈블리는 대입시에 모든 값에 캐스팅을 통해 형을 정해주어야 한다.

     

     

    어셈블리의 print  



    어셈블리는 printf 가 없다.


     %include "asm_io.inc"


    위 파일에서 printf 함수를 제공해 준다.

     

    print_int

    eax

    eax 값을 정수로 출력한다.

    print_char

     

    eax 값을 문자로 출력 한다.

    print_string

    eax

    eax 값을 문자열 출력

    print_nl

     

    엔터 (\n)

    read_int

    eax

    숫자를 입력 받는다.

    read_char

    eax

    문자를 입력 받는다.

    Dump_regs

     

    레지스터값을 16진수로 출력 FLAGS 의 bit도 출력

    Dump_mem

     

    메모리를 출력한다.

    Dump_stack

      

      

    어셈블리에서는 메모리 영역을 따로 생성 해주어야 한다.



    segment .data

    segment .bss

    segment .text ( code 영역 )


    global    _asm_main

     


    ※ global 은 외부에서 함수를 볼수있게 한다.


    어셈블리의 문자열은 다음과 같이 생성한다.


     prompt1 db    "Enter a number : ", 0


    return  어셈블리에서 ret 로 표시한다.

     

    pusha : a 는 all 을 뜻하고 push 는 메모리에 모두 넣고 esp ( top of stack )를 위로 올린다. 


    popa : pop은 push로 넣은 정보의 레지스터를 초기화 해준다. 


    함수 호출은 다음과 같다.



    mov    eax, prompt1

    call    print_string

     


    prompt1 (문자열) 의 주소를 eax 에 넣고 위 함수를 호출하면 prompt1 의 문자열이 출력 된다. 


    Ex) 출력 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    %include "asm_io.inc"
     
    segment  .data
     
    test_msg db  "Hello Assembly",0
     
     
     
    segment  .text
      global  _asm_main
     
    _asm_main:
      enter  0,0
      pusha
     
      mov  EAX, test_msg
      call  print_string  
      
      call  print_nl
      popa
      mov  eax, 0
      leave
       ret
    cs


    < 실행 결과 > 


    입력받는 함수



    call    read_int

    mov    [input1], eax

     


    input1에 C의 sanf 와 같이 입력 받는다. 


     dump_regs  : 레지스터 값을 16진수로 출력한다. 


     dump_mem  : 메모리를 출력한다. 


    어셈블리에서 함수를 호출할 때 함수이름 앞에 언더바( _ ) 를 붙인다.



    _asm_main : 

     

    -l     FileName



    DOS에서 어셈블리 파일의 메모리값을 보여준다.

     

     

     

     

     













     

     

     



    728x90
    반응형
상단으로