Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- epoll
- LOB
- BOF
- .nret core 배포
- REDIS
- cbpf
- edge trigger
- vtable
- NAPT
- packet flow
- wnourefresh
- rfc5508
- wrefresh
- mvwin
- Docker
- iptables
- ioctl
- doupdate
- DOCKER-USER
- level trigger
- 풀이
- packet filter
- ncurses
- C언어
- architecture
- 어셈블리어
- epoll_wait
- .net core 7
- Compiler
- 취약점
Archives
- Today
- Total
Tuuna Computer Science
[어셈블리] 파일 다루기 ( 소문자를 대문자로 바꾸기 ) 본문
- 파일 다루기
유닉스 파일 :: 프로그램에 의해 생성되며 바이트의 연속된 스트림으로 읽을 수 있다.
파일에 주어진 고유한 이름(번호)으로 파일에 접근할 수 있다 -> 파일 디스크립터
- open의 시스템 콜 :: 5번
open은 파일의 이름, 모드, 권한등을 인자로 받는다.
파일의 이름은 %ebx에 저장하고
모드는 %ecx에 저장한다.
읽기로 연다면 0을 쓰기위해서 03101을 저장하면 된다. (반드시 가장 앞에 0을 붙여야 함)
권한은 %edx에 저장 ex) 0666 모든 유저 읽기 쓰기 가능
리턴값은 %eax에 저장된다. :: 파일의 번호 리턴
- read의 시스템 콜 3번 :: 리턴 값 읽어들인 바이트 수
파일 지정자 :: %ebx에 저장
읽어들인 데이터가 저장될 버퍼의 주소 :: %ecx에 주소값을 저장
버퍼의 크기 :: %edx에 저장
버퍼는 section .bss를 이용해서 지정할 수 있다.
- write의 시스템 콜 4번 read함수와 기능 동일 (전달 제외)
- 버퍼와 .bss
버퍼 :: 대량의 데이터를 전달하기 위해서 사용되는 연속되는 블럭영역
고정된 크기의 버퍼와 동적크기의 버퍼로 나뉜다.
고정된 크기의 버퍼는 .long이나 .byte를 이용해서 버퍼로 사용될 크기를 직접 저장
단점 :: 저장공간의 낭비, 자료형의 판단 미스
해결 :: .text, .data 섹션을 사용
.bss 섹션은 저장공간을 확보할 수 있지만 초기화 할수는 없다.
.data 섹션의 경우 공간을 확보하고 값을 초기화 할 수 있다.
이렇듯 초기화할 필요없는 공간을 확보하고자 할 때 주로 사요된다. (.bss)
.section .bss
.lcomm my_buffer, 500 # .lcomm은 500byte의 공간을 할당하고, 공간을 가리키기 위한 심볼로 my_buffer을생성
movl $my_buffer, %ecx #데이터가 저장될 버퍼의 주소 값
movl 500, %edx #버퍼의 크기
movl 3, %eax #시스템 콜
int $0x80 #해당 시스템 콜 처리
위 코드는 read(fd, my_buffer, 500)이다.
$my_buffer 함으로써 immediate모드 어드레스 상태가 되고 버퍼의 시작위치를 가리키게 된다.
.equ는 일종의 별칭을 만들어 주기 위해서 사용되는 지시어 C언어의 #define과 비슷한 일
.equ LINUX_SYSCALL 0x80
int $LINUX_SYSCALL을 사용 가능 ($0x80)
1 # 하는일 : 파일로 부터 문자를 읽어들이고 대문자로 바꾼후 다른 파일로 저장한다.
2
3 #프로세스 : 1. 읽을 파일을 연다. 2. 쓸 파일을 연다. 3. 파일의 끝이 아니라면 반복한다
4
5 #반복 : 파일로 부터 문자열을 읽어서 메모리에 넣는다.
6 # 메모리로 부터 각 문자를 대문자로 변경한다.
7 # 변경된 문자는 파일로 저장한다.
8
9 .section .data
10
11 #상수들
12
13 .equ SYS_OPEN, 5
14 .equ SYS_WRITE, 4
15 .equ SYS_READ, 3
16 .equ SYS_CLOSE, 6
17 .equ SYS_EXIT, 1
18
19 #open()에 사용할 옵션
20
21 .equ O_RDONLY, 0 #읽기만 한다?
22 .equ O_CREATE_WRONLY_TRUNC, 03101 #쓰기 전용인데 없으면 만들고 초기화한 상태에서 쓰기 전용
23
24 #표준 파일 지정자
25
26 .equ STDIN, 0
27 .equ STDOUT, 1
28 .equ STRERR, 2
29
30 #시스템 콜 중단(interrupt)
31
32 .equ LINUX_SYSCALL, 0x80
33 .equ END_OF_FILE, 0 #파일의 끝을 검사하기 위해서 사용
34 #read()의 리턴값과 비교한다.
35
36 .equ NUMBER_ARGUMENTS, 2 #?
37
38 .section .bss
39 #버퍼 - 파일로 부터 데이터를 읽어들인 데이터를 저장하기 위한 목적으로 사용
40
41 #버퍼의 크기는 16000을 초과할 수 없다
42 .equ BUFFER_SIZE, 500
43 .lcomm BUFFER_DATA, BUFFER_SIZE #BUFFER_DATA라는 버퍼가 500byte크기의 공간을 할당한다.
44
45 .section .text
46
47 # 스택 위치
48
49 .equ ST_SIZE_RESERVE, 8 #?
50 .equ ST_FD_IN, -4
51 .equ ST_FD_OUT, -8
52 .equ ST_ARGC, 0 #인자의 개수
53 .equ ST_ARGV_0, 4 #프로그램의 이름 파라미터들이네
54 .equ ST_ARGV_1, 8 #읽어들일 파일의 이름
55 .equ ST_ARGV_2, 12# 저장할 파일의 이름
56
57
58 .global _start
59
60 _start:
61
62 ###초기화 관련###
42 .equ BUFFER_SIZE, 500
43 .lcomm BUFFER_DATA, BUFFER_SIZE #BUFFER_DATA라는 버퍼가 500byte크기의 공간을 할당한다.
44
45 .section .text
46
47 # 스택 위치
48
49 .equ ST_SIZE_RESERVE, 8 #?
50 .equ ST_FD_IN, -4
51 .equ ST_FD_OUT, -8
52 .equ ST_ARGC, 0 #인자의 개수
53 .equ ST_ARGV_0, 4 #프로그램의 이름 파라미터들이네
54 .equ ST_ARGV_1, 8 #읽어들일 파일의 이름
55 .equ ST_ARGV_2, 12# 저장할 파일의 이름
56
57
58 .global _start
59
60 _start:
61
62 ###초기화 관련###
63 #스택포인터를 저장한다.
64 movl %esp, %ebp
65
66 #스택에 파일 지정자를 저장하기 위한 공간을 할당한다.
67 subl $ST_SIZE_RESERVE, %esp
68
69 open_files:
70
71 open_fd_in:
72 ### 읽어들일 파일을 연다.
73 movl $SYS_OPEN, %eax #system call
74 movl ST_ARGV_1(%ebp), %ebx #ebx에 파일이름을 넣는다.
75 movl $O_RDONLY, %ecx #read_only flag
76 movl $0666, %edx #파일권한을 0666
77 #위 3개는 모두 open함수의 인자들임
78 int $LINUX_SYSCALL #리눅스 호출
79
80 store_fd_in:
81 movl %eax, ST_FD_IN(%ebp) #리턴된 파일 지정자를 저장한다.
82
83 open_fd_out:
84 #저장할 파일 열기
85
86 movl $SYS_OPEN, %eax #파일 열기
87 movl ST_ARGV_2(%ebp), %ebx #열 파일이름을 지정
88 movl $O_CREATE_WRONLY_TRUNC, %ecx #쓰기위한 플래그 설정
89 movl $0666, %edx #파일 권한
90 int $LINUX_SYSCALL
91
92 store_fd_out:
93 movl %eax, ST_FD_OUT(%ebp) #파일 지정자를 저장한다.
94
95
96 read_loop_begin:
97
92 store_fd_out:
93 movl %eax, ST_FD_OUT(%ebp) #파일 지정자를 저장한다.
94
95
96 read_loop_begin:
97
98 ### 파일로 부터 읽어들이는 부분
99 movl $SYS_READ, %eax
99 movl $SYS_READ, %eax
100 movl ST_FD_IN(%ebp), %ebx #읽어들일 파일 지정자
101 movl $BUFFER_DATA, %ecx #버퍼의 주소 값을 넘김
102 movl $BUFFER_SIZE, %edx #읽어들일 크기를 준다.
103 int $LINUX_SYSCALL #리턴 값은 %eax에
104
105 cmpl $END_OF_FILE, %eax #파일의 끝인지 검사한다.
106 jle end_loop #만약 끝이라면
107
108
109 continue_read_loop:
110 ###입력된 문자를 대문자로 변경하는 부분 ###
111 pushl $BUFFER_DATA #버퍼의 위치
112 pushl %eax #버퍼의 사이즈 ( read함수의 리턴값은 읽어들인 바이트수다)
113 call convert_to_upper #대문자 변경함수 호출
114 popl %eax
115 addl $4, %esp
116
117 ###변경된 문자를 파일에 쓴다. ###
118
119 movl %eax, %edx #버퍼의 크기
120 movl $SYS_WRITE, %eax
121 movl ST_FD_OUT(%ebp), %ebx #저장에 사용할 파일 지정자
122 movl $BUFFER_DATA, %ecx #버퍼의 위치를 준다
123 int $LINUX_SYSCALL
124
125 ###루프를 수행
126 jmp read_loop_begin #이거 어떻게 탈출 그럼?
127
128 end_loop:
129 ###파일을 닫는다 ###
130 movl $SYS_CLOSE, %eax
131 movl ST_FD_OUT(%ebp), %ebx #왜 2번 파일을 닫지 write하는 파일
132 int $LINUX_SYSCALL
133
134 ### 종료 코드 ###
135
136 movl $SYS_EXIT, %eax
137 movl $0, %ebx
138 int $LINUX_SYSCALL
139
140 # 소문자를 대문자로 변경
141
142 .equ LOWERCASE_A, 'a'
143 .equ LOWERCASE_Z, 'z'
144 .equ UPPER_CONVERSION, 'A' - 'a'
145
146 .equ ST_BUFFER_LEN, 8
147 .equ ST_BUFFER, 12
148
149 convert_to_upper:
150
151 pushl %ebp
152 movl %esp, %ebp
153 movl ST_BUFFER(%ebp), %eax #12면 메모리를 그렸을 때 read했던 파일디스크립터다
154 movl ST_BUFFER_LEN(%ebp), %ebx
155 movl $0, %edi
156
157 cmpl $0, %ebx #loop count?
158 je end_convert_loop
159
160
161 convert_loop:
162
163 movb (%eax, %edi, 1), %cl #cl = eax에서 + edi * 1이렇게네
164
165 cmpb $LOWERCASE_A, %cl
166 jl next_byte #cl이 더크다면
167 cmpb $LOWERCASE_Z, %cl
168 jg next_byte #cl이 더 작다면
169
170 addb $UPPER_CONVERSION, %cl #아스키 값을 더함
171 movb %cl, (%eax, %edi, 1) #다시 그 위치에 가져다 놓는다.
172
173 next_byte:
174
175 incl %edi
176 cmpl %edi, %ebx # %ebx는 버퍼에 적인 문자열의 길이
177 jne convert_loop
178
179 end_convert_loop:
180
181 movl %ebp, %esp
182 popl %ebp
183 ret
밑에 사진은 위 코드의 메모리를 그림으로 본떴다.
여러분도 어셈블리공부하다가 메모리구조를 까먹었다면 그리길 추천합니다...
'Assembly' 카테고리의 다른 글
[어셈블리어] 최소공배수 구하기 (0) | 2018.08.30 |
---|---|
[어셈블리어] 구구단 출력하기 (0) | 2018.08.30 |
재귀함수 호출시 스택프레임상황 (0) | 2018.06.12 |
C 언어 문자열 관련 함수 (strcpy) 분석 (0) | 2018.06.11 |
포인터 배열 (0) | 2018.06.11 |
Comments