본문 바로가기
코스웨어/12년 내장형하드웨어

[Assembly] Chapter 1 정리자료 By.임창엽

by 알 수 없는 사용자 2012. 8. 22.
728x90
반응형





 

[ Chapter 1 ]

 








 

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

 

 

 

 

 

 

 






 

★ nasm 컴파일

 

 

Ex) asm_io.asm 파일 내부

%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

 

 

 




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

 



 

 

 





 

 

 

Ex) first.asm 파일 내부

%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
  




 

 


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

 





 

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

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
%

 

 

 

 

Ex) drive.c 파일 내부

#include <stdio.h>

int main()
{
  
int ret_status;
  ret_status = asm_main();
  
return ret_status;
}

 





위와 동일한 방법으로 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

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

 


    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) 출력

%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

 

 

 


< 실행 결과 >


 

 

 

 



입력받는 함수


     call    read_int

    mov    [input1], eax

 


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

 


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

 


dump_mem : 메모리를 출력한다.

 


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


    _asm_main :

 

 

 

    -l     ileName


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








728x90