첨부파일에는 컴파일 링크시 필요한 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=4 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=1 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 | Q |
ten bytes | T |
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에서 어셈블리 파일의 메모리값을 보여준다.
Assembly(Assembly 기초/C소스 어셈블리로 코딩하기) (0) | 2017.07.25 |
---|---|
Assembly (어셈블리/함수호출규약 cdecl, stdcall, pascal /MSAM /ml 컴파일/디버깅) (0) | 2017.07.18 |
어셈블리 기초 (0) | 2017.07.18 |