No img


Assembly -1. HelloWorld!

Posted by bonggang | 2019. 7. 6. 01:30

어셈블리 공부를 해야할 일이 생겼다.

근데 다른 언어들, 지식들에 비해 어셈블리어는 한글로 설명하는 글이 매우 적거나 리눅스 우분투 환경이 아닌 윈도우 비쥬얼스튜디오를 사용해서 나에게 맞지 않는 글이 더 많았다.

필요한 정보가 없는건 아닌데 부족한 느낌, 내가 못 찾았을 가능성이 매우 높지만 결국 유튜브에서 영어로 설명하는 영상으로 공부를 시작했다.

 

어셈블리어는 컴퓨터 프로그래밍 언어 가운데 하나로서, 기계어를 사람이 일상 생활에서 사용하는 자연어에 가깝게 문자로 기호화해서 나타낸 것이다. 기계어와 어셈블리어는 각각의 중앙처리장치(CPU) 형태에 따라 그 내용이 모두 다르므로 어셈블리언어로 작성된 프로그램들은 한 종류의 CPU에서만 동작하고 다른 종류에서는 실행되지 않는다.

 


환경: Linux ubuntu 16.0.4

Assembly 언어를 사용하기 전에 sudo apt-get install nasm를 입력해 nasm을 설치해주세요.

 

코딩의 세계에서 가장 먼저 배우는 것은 역시 HelloWorld! 출력하기가 정석인것 같기에 먼저 helloWorld 출력을 통해 기초를 알아보도록 하자.

 

먼저 터미널을 켠 다음 코드 파일을 생성해줘야한다. 여기서 잠깐, 어셈블리어로 만든 파일의 확장자는 *.asm이다.

터미널에서 nano fileName.asm을 입력해준다. (nano가 아닌 다른 편집기를 쓰셔도 괜찮습니다.)

그 후 아래 그림과 같이 입력해다.

 

다른 언어들에 익숙한 사람들은 이것이 무엇인가 의아해 하고 있을지도 모른다.

지금부터 하나하나 살펴보도록 하자.

 

1. Section

모든 x86_64 어셈블리 파일은 3개의 영역을 소유합니다.

[.data / .bss / .text]

- data section: 컴파일 전 모든 데이타들이 정의되는 곳.

- bss section: 미래의 사용을 위해 데이터를 할당해두는 곳.

- text section: 실제 코드 기술

 

 

 

 

 

2. db

- define some raw bytes of data to insert into our code.

- 1byte를 쓰는 명령, 문자열을 쓸 경우 각각의 문자코드를 조사하여 그것을 1byte 씩 나열

- Hello WOrld! 뒤의 10은 개행문자

- db 앞 text는 데이터가 위치한 메모리의 주소에 이름을 할당한 것

db dw dd dq dt
byte word(2bytes) 2중워드(4bytes) 4중워드(8bytes) 10bytes

3. global

- 다른 파일이 레이블에 접근할 수 있도록 링커에 label의 주소를 알려줌

- global _start은 _start 레이블이 전역에 선언된 레이블임을 의미하는 어셈블러 지시어

 

4. Labels

- 소스 코드 안의 위치를 식별

- 컴파일하는 즉시, 컴파일러가 라벨이 메모리의 위치를 계산

- _start: 라벨은 프로그램 필수 요소, 프로그램이 컴파일 되고 실행될 때 가장 먼저 실행되는 부분

 

5. Register & System call

- Register: a part of the processor that temporarily holds memory, 어셈블리에서 사용 되는 기본 변수 이름

-> 다른 언어와 달리, 하드웨어적으로 구현 됨, 이름 변경 불가능, CPU 종류 별로 레지스터 이름이 다름.

-> 종류: RAX(함수 반환 값), RBX(메모지 주소 저장), RCX(반복 카운터), RDX, RSI(source), RDI(description), RBP(현재 함수 Base Point), RSP(현재 스택 최상위 값), RIP(다음에 수행될 코드 영역)

Argument ID 1 2 3 4 5 6
Register rax rdi rsi rdx r10 r8 r9

- System call: program requests a service from the kenel

syscall ID ARG1 ARG2 ARG3
sys_read 0 #filedescriptor $buffer #count
sys_write 1 #filedescriptor $buffer #count
sys_open 2 $filename #flags #mode
sys_close 3 #filedescriptor    

- sys wirte

type description
file description

0(standard Input)

1(standard Output)

2(standard Error)

Buffer Location of string to write
Count Length of string

그럼 이제 다시 코드를 살펴보자

section .data 부분

- db를 이용해 text에 "Hello WOrld!"와 줄바꿈문자를 저장해주었다.

 

section .text 부분

- _start: 라벨을 통해 실행되기 때문에 시작과 동시에 _printHello 라벨을 호출했다.

- _printHello 라벨에서는 Hello WOrld!" 즉 text에 저장된 것을 출력해주어야한다.

- system call 중 출력을 위해 사용하는 것은 sys_write이며 sys_write는 ID, #filedescriptor, &buffer, #count를 요구한다. 각각의 의미는 위의 표를 참조 이해한 후 적어준다.

 

-printHello 호출이 종료된 후 프로그램 실행 종료를 해주기 위해

mov rax, 60/ mov rdi, 0 / syscall을 작성해줬다.

 

 

코드를 다 입력한 후 nasm -felf64 파일이름.asm; ld -o 이름 파일이름.o를 해서 실행결과를 확인.

'CS > Assembly' 카테고리의 다른 글

Assembly -4. for문 구현  (0) 2020.05.26
Assembly -3. 간단한 에코 프로그램  (1) 2020.05.25
Assembly -2. 기본 문법, 명령  (0) 2019.07.07