ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ Assembly 구구단_NASM ]
    System/Reversing 2018.07.16 14:57

    BoB 과제 중 Assembly로 구구단 프로그램 만드는 과제가 있었다.

    외부 라이브러리(printf, scanf)을 사용해도 좋다고 하셨지만, 한번 외부 함수 없이 구현해보고 싶었다.


    Assembler 종류는 대표적으로 MASM(Microsoft) / NASM(Netwide) / GAS(Gnu) 가 있는데

    나는 Intel문법을 지원하는 NASM 어셈블러를 사용했고, 64bit 환경에서 구현하였다.


    명령어 : nasm -felf64 gugudan.asm    .asm -> .o

       ld -o gugudan gugudan.o    .o -> execute




    [ Assembly 구구단 ]


    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
    global _start
     
    ;#####################Text Section###################
    section .text
     
    _start:
        mov rax, 1
        mov rdi, 1
        mov rsi, welcome
        mov rdx, 49
        syscall    ;write
     
        mov rax, 1
        mov rdi, 1
        mov rsi, input
        mov rdx, 16
        syscall    ;write
     
        xor rax, rax
        xor rdi, rdi
        mov rsi, sel
        mov rdx, 2
        syscall    ;read
        
        mov rax, sel
        cmp byte[rax], 0x31
        je m_1
        
        call menu_2
        mov rax, 60
        xor rdi, rdi
        syscall    ;exit    
     
        m_1:
            call menu_1
            mov rax, 60
            xor rdi, rdi
            syscall    ;exit
     
    menu_1:
        mov rcx, 9
        mov rax, '1'
     
        lp_1:
            mov [X], al
            push rcx
            mov rax, '1'
            mov rcx, 9
        
        lp_2:
            push rax
            push rcx
            mov [Y], al
            call print_X
            call print_space
            call print_star
            call print_space
            call print_Y
            call print_space
            call print_equal
            call print_space
            call print_Z
            call print_enter
            pop rcx
            pop rax    
            inc al
            loop lp_2    ; count == 9
            call print_enter
            pop rcx
            mov rax, [X]
            inc al
            loop lp_1
            ret
     
    menu_2:
        xor rax, rax
        xor rdi, rdi
        mov rsi, dan    
        mov rdx, 2
        syscall
     
        mov al, [dan]
        mov [X], al    
        mov rcx, 9
        mov rax, '1'
        
        nlp_1:
            push rax
            push rcx
            mov [Y],al
            call print_X
            call print_space
            call print_star
            call print_space
            call print_Y
            call print_space
            call print_equal
            call print_space
            call print_Z
            call print_enter
            pop rcx
            pop rax
            inc al
            loop nlp_1
            ret
        
     
    ;####################Function Section####################
    print_star:
        mov rax, 1
        mov rdi, 1
        mov rsi, star
        mov rdx, 1
        syscall
        ret    
     
    print_equal:
        mov rax, 1
        mov rdi, 1
        mov rsi, equal
        mov rdx, 1
        syscall
        ret    
     
    print_space:
        mov rax, 1
        mov rdi, 1
        mov rsi, space
        mov rdx, 1
        syscall
        ret    
     
    print_enter:
        mov rax, 1
        mov rdi, 1
        mov rsi, enter
        mov rdx, 1
        syscall
        ret
     
    print_X:
        mov rax, 1
        mov rdi, 1
        mov rsi, X
        mov rdx, 1
        syscall
        ret
     
    print_Y:
        mov rax, 1
        mov rdi, 1
        mov rsi, Y
        mov rdx, 1
        syscall
        ret
     
    print_Z:
        mov al, [X]
        sub al, '0'    ;char -> dec
        mov bl, [Y]
        sub bl, '0'    ;char -> dec
        mul bl    ; X * Y
        mov bl, 10
        div bl
        add al, '0'
        add ah, '0'
        cmp al, '0'
        je no_up
        
        mov [Z+1], ah
        mov [Z], al
        mov rax, 1
        mov rdi, 1
        mov rsi, Z
        mov rdx, 2
        syscall
        ret
        
        no_up:
            mov byte [Z], ah
            mov rax, 1
            mov rdi, 1
            mov rsi, Z
            mov rdx, 1
            syscall
            ret
     
    ;###################Data Section####################
    section .data
    welcome: db "Welcome! Print Gugudan!",10,"[1] 1~9Dan / [2] (N)Dan", 10,0
    input: db "Please Input > ", 0
    sel: dw 0x00
    dan: dw 0x00
    X: db '1'
    Y: db '1'
    Z: dw '1'
    star: db '*'
    equal: db '='
    space: db ' '
    enter: db 10
     
    cs




    [ 실행 모습 ]


    [ 1단 ~ 9단 출력 ]

      


    [ 입력받은 N단 출력 ]




    [ 여담 ]

    어셈블리어로 프로그램을 짜본적이 없어서 하나부터 열까지 힘들었다..

    메뉴 선택 할 때, 분기시키는 로직짜는 것도 2시간 디버깅 끝에 구현 할 수 있었다.


    메뉴선택 Input값을 비교할 때, 

    CMP RAX, 0x31 이렇게 비교를 했었는데, 이건 RAX의 주소와 비교를 하는 것과 똑같은 구문이다.

    따라서, CMP [RAX], 0x31 과 같이 대괄호로 묶어줘서 값을 참조하게 하여서 비교해야 한다.


    이 것 외에도 연산값 출력하는 것, 반복문 돌리는 것 등등 난관이 너무 많았다..

    이 간단한 프로그램 짜는데만 거의 10시간정도 걸린 것 같다.

    그래도 어셈블리어 해석능력(리버싱)이 향상된 것 같아서 의미없는 시간은 아니였다. 

    'System > Reversing' 카테고리의 다른 글

    [ Assembly 구구단_NASM ]  (3) 2018.07.16
    32Bit(x86)/64Bit(x64) 차이점 정리  (0) 2018.02.04

    댓글 3

    • 프로필사진

      우리 수업시간에 내가 어셈으로 구구단 짜보라고 했자너 ..
      왜이제하고 어렵다고해 ㅋㅋㅋ
      그리고 어셈은 곱셈말고 나눗셈이 진퉁임 ㅎㅎ :)

      2018.07.19 10:52
      • 프로필사진

        ㅋㅋㅋㅋㅋㅋㅋ 그러게요..
        비오비와서 형한테 배운 것들 엄청 유용하게 활용하고 있어요ㅎㅎ

        2018.07.20 16:50 신고
    • 프로필사진

      어셈블리로 짜는게 머리 아프네요 진짜 ㅠㅠ 잘 보고갑니다

      2019.04.06 03:23
Designed by Tistory.