Language/Assembly

ASSEMBLY 기초/문법

Dexter_- 2017. 7. 18. 17:50
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
반응형