어셈블러 포맷

어셈블러의 포맷에 대해서 알아보겠습니다.

 

어셈블러가 하는 일은 소스코드를 컴파일하여

CPU가 해석가능한 기계어 코드를 만드는 것인데

이것도 일종의 프로그램이므로 어셈블러마다

각각 포맷이 있습니다. 예를 들어 MASM과

NASM은 다른 포맷입니다. 같은 CPU를

사용해도 운영체제가 다르면 또 프로그램이

달라지니까 어셈블러는 하드웨어와

플랫폼에 의존적이라고 말할 수 있습니다.

 

요즘은 C언어에도 호환성이 있는 시대인데

java와 같은 write once run anywhere가 모토인

크로스 플랫폼과는 전혀 관계가 없기 때문에

이런 것들을 배우는게 시간낭비고 도움이

안된다는 아이디어도 충분히 설득력이 있습니다

 

다만 어셈블리어를 배우는 이유는

어셈블리어로 뭔가 쎄끈한 프로그램을

만들겠다는 것보다는 java나 C#같은

고수준 언어와 운영체제의 시스템을

더 잘 이해하기 위한 부분과 또는

성능에 최적화된 모듈을 직접 개발해야 할때

유용하게 사용할 수 있습니다.

(C언어는 어셈블리어 코드를 가져올 수 있다.

C확장을 사용하면 파이썬에서도 어셈블리어

코드를 실행하는 C언어를 사용할 수 있다)

 

section 들 (data, bss, text section)

우선 section 혹은 segment에 따라

무슨 차이가 있는지 알아보겠습니다.

 

아래 코드에서 보면 section .data는

초기화된 데이터가 들어갑니다.

 

section .bss 는 초기화되지 않은 데이터입니다.

 

section .text 는 명령어(코드)가 들어갑니다.

 

이 세개가 기본 section 입니다.

segment라는 키워드도 같은 의미로 사용합니다.

 

section .data
;for initialized data
;data should be initialized (of course it should be)
    welcomeMSG: db "Hello NASM sections!",10,0
    len: equ $-welcomeMSG ;constant

section .bss
;for uninitialized data
    someValue: resq 1 ;3 element byte array

section .text
    global _start

_start:
    nop ;just a placeholder
    mov rax, 1
    mov rdi, 1
    mov rsi, welcomeMSG
    mov rdx, len
    syscall

    mov dword [someValue], dword 123

_exit:
    mov rax, 60
    mov rdi, 0
    syscall

 

컴파일한 Makefile 입니다

 

all:
	nasm -g -F dwarf -f elf64 main.asm -o main.o
	ld main.o -o main
	./main

readelf 를 사용해서 보면 section header에

.data .bss .text 가 있습니다.


ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          64 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         18
  Section header string table index: 4

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .data             PROGBITS         0000000000000000  000004c0
       0000000000000016  0000000000000000  WA       0     0     4
  [ 2] .bss              NOBITS           0000000000000000  000004e0
       0000000000000008  0000000000000000  WA       0     0     4
  [ 3] .text             PROGBITS         0000000000000000  000004e0
       0000000000000033  0000000000000000  AX       0     0     16
  [ 4] .shstrtab         STRTAB           0000000000000000  00000520
       00000000000000ca  0000000000000000           0     0     1
  [ 5] .symtab           SYMTAB           0000000000000000  000005f0
       0000000000000138  0000000000000018           6    12     8
  [ 6] .strtab           STRTAB           0000000000000000  00000730
       0000000000000030  0000000000000000           0     0     1
  [ 7] .rela.text        RELA             0000000000000000  00000760
       0000000000000030  0000000000000018           5     3     8
  [ 8] .debug_aranges    PROGBITS         0000000000000000  00000790
       0000000000000030  0000000000000000           0     0     1
  [ 9] .rela.debug_arang RELA             0000000000000000  000007c0
       0000000000000030  0000000000000018           5     8     1
  [10] .debug_pubnames   PROGBITS         0000000000000000  000007f0
       0000000000000012  0000000000000000           0     0     1
  [11] .debug_info       PROGBITS         0000000000000000  00000810
       000000000000004a  0000000000000000           0     0     1
  [12] .rela.debug_info  RELA             0000000000000000  00000860
       0000000000000078  0000000000000018           5    11     1
  [13] .debug_abbrev     PROGBITS         0000000000000000  000008e0
       000000000000001b  0000000000000000           0     0     1
  [14] .debug_line       PROGBITS         0000000000000000  00000900
       0000000000000045  0000000000000000           0     0     1
  [15] .rela.debug_line  RELA             0000000000000000  00000950
       0000000000000018  0000000000000018           5    14     1
  [16] .debug_frame      PROGBITS         0000000000000000  00000970
       0000000000000004  0000000000000000           0     0     8
  [17] .debug_loc        PROGBITS         0000000000000000  00000980
       0000000000000010  0000000000000000           0     0     1

Symbol table '.symtab' contains 13 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS main.asm
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     5: 0000000000000000     1 OBJECT  LOCAL  DEFAULT    1 welcomeMSG
     6: 0000000000000016     0 NOTYPE  LOCAL  DEFAULT  ABS len
     7: 0000000000000000     1 OBJECT  LOCAL  DEFAULT    2 someValue
     8: 0000000000000027     0 NOTYPE  LOCAL  DEFAULT    3 _exit
     9: 0000000000000000     0 SECTION LOCAL  DEFAULT   11 
    10: 0000000000000000     0 SECTION LOCAL  DEFAULT   13 
    11: 0000000000000000     0 SECTION LOCAL  DEFAULT   14 
    12: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    3 _start

No version information found in this file.

소스코드 작성방법

주석(Comments)

주석은 ; 다음에 나오는 텍스트입니다.

명령어 다음에 나와되 됩니다.

 

;주석입니다.

mov rax, 1 ;명령어 다음에 주석입니다

 

이렇게 쓰면 됩니다.

16진수 표기, 8진수 표기

소스코드 상에서 16진수는 0x 접두어를 붙입니다.

 

mov rax, 60 이면 mov rax, 0x3c 처럼 바꿀 수 있습니다.

 

8진수는 q를 접미어로 붙입니다.

예를 들어 8은 10q 입니다.

 

기본은 물론 10진수입니다.

section .data

데이타 섹션은 초기화된 데이타가 들어갑니다.

 

여기에 초기화된 데이터를 선언합니다.

여기에는 고수준 언어처럼 char, int 이런 것은

없지만 바이트 수로 따집니다.

 

db - define byte, 8 bit

dw - define word, 16 bit

dd - define double word, 32 bit

dq - define quad word, 64 bit

 

아래 예제는 .data 섹션에서 변수를

선언하는 예제입니다.

 

여러개의 요소를 할당하는 배열도

선언하고 초기화 할 수 있습니다.

부동소수점도 선언할 수 있습니다.

section .data
;for initialized data
;data should be initialized (of course it should be)
    byteVar   db 10               ;byte - gdb: cast char
    charVar   db "A"              ;character
    strVar    db "This is string" ;string
    wordVar   dw 30000            ;16-bit - gdb: cast short
    doubleVar dd 1000000000       ;32-bit - gdb: cast unsigned int
    quadVar   dq 5000000000       ;64-bit - gdb: cast unsigned long

    wordArray dw 15,30,35         ;3 element array
    floatVar  dd 1.234567         ;float - gdb: cast float

section .bss

segment .text
    global _start

_start:
    mov byte [byteVar], byte 100
    mov word [wordVar], word 65535
    mov dword [doubleVar], dword 2500000000

    mov al, byte [byteVar]
    mov ax, word [wordVar]
    mov eax, dword [doubleVar]
    mov rax, qword [quadVar]

_exit:
    mov rax, 0x3c
    mov rdi, 0x0
    syscall

 

text 섹션에서 사용하는 방법은

조금 차이가 있는데 레지스터는

al, ax, eax, rax 만 봐도 비트수가

확인이 되지만 변수는 몇 비트인지

그 이름만 가지고는 알 수 없습니다.

따라서 비트수를 지정해주는데

그 주소에서 비트만큼 접근해서

사용하기 때문입니다. 이것을

맞추지 않으면 대개는 컴파일러

에러나 워닝 메시지를 볼 수 있습니다.

 

여기에는 C언어 처럼 char, int 같은

기본 데이터형이 있는게 아닙니다.

바이트수를 기준으로 맞추는 거라서

좀 tricky 합니다. 이거를 매번 출력하면서

확인하는 것은 어려우니까 gdb 디버거를

좀 활용하는게 도움이 됩니다.

 

 

어셈블리어 GDB 디버거 사용법(기본) - NASM x86_64 어셈블리어 7

 

어셈블리어 GDB 디버거 사용법(기본) - NASM x86_64 어셈블리어 7

GDB 디버거 GDB 디버거는 GNU Project Debugger의 약자로 GNU toolchain 핵심 구성요소 중에 하나입니다. www.sourceware.org 에서는 GDB의 정의를 GDB, the GNU Project debugger, allows you to see what is goi..

digiconfactory.tistory.com

 

 

공유하기

facebook twitter kakaoTalk kakaostory naver band