나빌로스를 한답시고 보면서

정작 어셈블리 공부를 제대로 안하고 이상한걸 보고 있었다가 다시 돌아왔다.

 

 

너무 깊이 배울 필요는 없어서 자료 찾다보니

kldp의 자료가 적당할거같고 

mov는 어떻게 쓰고, jmp는 어떻게 쓰고 하는 자질구래한 내용들 많은 강좌보다는

섹션이 뭐고 다 포함하고 

이 내용을 따라했다.

https://wiki.kldp.org/HOWTO/html/Assembly-HOWTO/x848.html

 

소개

마침내 때가 왔다. 여러분이 아직도 이 문서를 읽고 있으며, 여전히 어셈블리로 무언가를 만들겠다는 광기어린(!) 생각을 가지고 있다면 (여기까지 읽은 사람이라면, 정말 어셈블리 팬임에 틀림

wiki.kldp.org

 

 

 

 

 

프로그램 레이아웃

- .text 섹션 : 작성한 코드

- .data 섹션 : 초기화된 데이터 

- .bss 섹션 : 초기화 되지 않은 데이터

 

 

NASM 코드 helloworld

 

section		.data						; 섹션 .data 선언

msg		db		"hello, world!", 0xa		; 출력할 문자열
len		equ		$ - msg				; 문자열 길이

section		.text						;여기부터 .text 섹션

	global _start						;ELF링커나 로더에게 프로그램 엔트리포인터알려줌.보통 _start

_start:
    mov		edx, len					; 시스템콜의 세번째 인수, 출력할 메시지 길이 가져옴
    mov		ecx, msg					; 시스템콜의 두번째 인수, 출력할 메시지 포인터 가져옴
    mov		ebx, 1						; 시스템콜의 첫번째 인수, 파일 디스크립터 전달.
    mov		eax, 4						; eax 레지스터에 시스템 콜번호 전달. 4번은 sys_write
    int		0x80						;커널 호출

; 출력 완료 후 exit 호출
    mov		ebx, 0						; exit 코드로 0을 준다.
    mov 	eax, 1						;시스템 콜 1번(sys_exit)
    int		0x80						;커널 호출

 

 

실행 결과

 

 

 

 

kldp 내용만 봐도 뭔지 대강알긴 하겠지만 설명이 좀 부족해보인다

 

여기보다는 이쪽 튜토리얼이 예제나 설명이 자세하다.

https://asmtutor.com/

 

 

NASM Assembly Language Tutorials - asmtutor.com

~$ nasm -f elf helloworld-input.asm ~$ ld -m elf_i386 helloworld-input.o -o helloworld-input ~$ ./helloworld-input Please enter your name: Daniel Givney Hello, Daniel Givney

asmtutor.com

 

 

lesson 1 예제를 보면

 

직접 어셈블리어로 하드웨어를 제어하고 싶을때 EAX 레지스터에다가 함수번호(오퍼레이션 코드)를 넣고,

나머지 레지스터에다가 필요한 값을 넣은 다음에, int 명령으로 소프트웨어 인터럽트를 주면 지정한 함수가 호출된다.

 

sys_exit()는 EAX=1을

sys_write()는 EAX=4 그리고 EBX, ECX, EDX에 필요한 값을 넣어주면 된다.

 

; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld
 
SECTION .data
msg     db      'Hello World!', 0Ah     ; assign msg variable with your message string
 
SECTION .text
global  _start
 
_start:
 
    mov     edx, 13     ; number of bytes to write - one for each letter plus 0Ah (line feed character)
    mov     ecx, msg    ; move the memory address of our message string into ecx
    mov     ebx, 1      ; write to the STDOUT file
    mov     eax, 4      ; invoke SYS_WRITE (kernel opcode 4)
    int     80h

 

위에서 설명한대로

SECTION .data

데이터 섹션 그러니까 초기화 되는 변수 부분을 나타내는데

msg라는 변수에다가  'hello world'를 담는건 알겠지만 왼쪽에 db와 우측에는 ,0ah가 존재한다.

 

 

이게 뭐소리인가 찾아보니

db는 바이트 데이터 형을 의미한다하고,

다른데도 찾아보니 msg에 바이트 단위 배열로 넣기 위한 자료형 선언한다는 의미라한다.

ref : https://velog.io/@kyoung99u/%EC%96%B4%EC%85%88%EB%B8%94%EB%A6%AC-%EC%96%B8%EC%96%B4

 

[Assembly] 어셈블리 기초

변수 어셈블리 프로그램에서 변수를 어떻게 사용할까? 어셈블리 프로그램에서는 타 프로그램과 같이 변수를 정의하여 사용하는데, 변수는 변수명과 데이터형, 초기값을 가진다. 0806 어셈블리언

velog.io

 

 

그러면 ,0ah는

쿼라에 질문올라온게 있긴한데

답변한 사람 말로는

0xA는 라인피드

0xD는 캐리지 리턴이라고 설명하고 있다.

그러면 0xAh는 뒤에 h가 붙어있는데 이건 뭔소린가 싶긴한데 설명이없다.

 

https://www.quora.com/What-is-the-meaning-of-0ah-0dh-in-assembly-language-for-displaying-any-message

 

What is the meaning of 0ah, 0dh in assembly language for displaying any message?

Answer (1 of 4): As everyone else answered, 0xA linefeed (\n), 0xD carriage return(\r), but have you wondered why is this two different notion in assembly? why did the carriage return and line feed was different back then ?? in high level languages when we

www.quora.com

 

 

여길 보니 0ah가 아스키 코드로 라인피드가 맞다고 하는걸 보니 답변자가 빠트린가 보다

https://www.sluiceartfair.com/2018/contributing/what-is-0ah-in-assembly/

 

What is 0AH in assembly? – Sluiceartfair.com

What is 0AH in assembly? 0Ah is the hexadecimal constant for the Line Feed character in ASCII, often abbreviated LF. 24h is the hexadecimal constant for the ‘$’ character in ASCII. What is carriage return in assembly language? Carriage Return Character

www.sluiceartfair.com

 

int 80h는 소프트웨어 인터럽트를 발생시키는 어셈블리 코드라고한다.

https://second.wiki/wiki/int_80h

 

Int 80h

Int 80h

second.wiki

 

 

일단 어셈블리와 링커를 돌린후 실행하보면 생각한데로 출력은 잘되는데 세그먼테이션 폴트가 뜬다.

이 문제는 다음 레슨에서 설명하는데

~$ nasm -f elf helloworld.asm
~$ ld -m elf_i386 helloworld.o -o helloworld
~$ ./helloworld
Hello World!
Segmentation fault

 

 

 

 

레슨 2 : 프로그램을 제대로 종료시키자

레슨 1에서는 어셈블리어로 sys_write 시스템 콜을 써서 출력을 시켰는데 이번 레슨에서는 sys_exit에 대해서 보자

설명이 쭉 있는데, 결국에는 모든 프로그램은 메모리를 공유하고 있다보니 global _start에서부터 순차적으로 실행해주는데 어디서 끝낼지 커널한태 알려주지 않으면 구현하지 않은 다음 주소에 있는것도 실행하게 되고 이게 세그먼테이션 폴트의 원인이 된다고 한다.

 

sys_exit를 쓰기 위해선

EBX에 0을 전달하도록 0을

EAX에 sys_exit를 호출하는 1을 넣으면 되서 코드는 이렇게 된다고 말한다.

; Hello World Program - asmtutor.com
; Compile with: nasm -f elf helloworld.asm
; Link with (64 bit systems require elf_i386 option): ld -m elf_i386 helloworld.o -o helloworld
; Run with: ./helloworld
 
SECTION .data
msg     db      'Hello World!', 0Ah
 
SECTION .text
global  _start
 
_start:
 
    mov     edx, 13
    mov     ecx, msg
    mov     ebx, 1
    mov     eax, 4
    int     80h
 
    mov     ebx, 0      ; return 0 status on exit - 'No Errors'
    mov     eax, 1      ; invoke SYS_EXIT (kernel opcode 1)
    int     80h

 

정상적으로 프로그램을 종료시켜서인지 세그먼테이션 폴트가 뜨지 않고 잘 끝낫다!

 

 

+ Recent posts