.text
read-only section
코드 영역이라고도 불리며, 상수 및 실행 코드인 기계어 코드들이 담겨 있다.
.end
프로그램이 끝나는 부분.
이후의 코드는 무시된다.
.data
말 그대로 데이터 영역.
global 변수와 static 변수가 여기에 들어간다.
다만, static은 공간만 할당되고, static 변수가 있는 함수가 실행될 때 초기화 된다.
프로그램이 시작할 때 할당되고, 종료될 때 반환된다.
여기서 초기화된 데이터는 .data에 들어가고,
초기화되지 않은 변수는 .bss 에 들어간다.
예시 코드를 보면
.text
.global _start
_start:
adr r4, a
ldr r0, [r4]
adr r4, b
ldr r1, [r4]
add r3, r0, r1 @ a + b
adr r4, c
ldr r2, [r4]
sub r3, r3, r2 @ ( a + b ) - c
ldr r4, =0x12345678
add r3, r3, r4 @ ( a + b ) - c
@ + 0x12345678
@ adr r4, x
ldr r4, =x
str r3, [r4]
@ check the result by gdb at this point
mov r7, #1 @ exit
mov r0, #0
swi 0
.align
a: .word 1234
b: .word 5678
c: .word 4567
.data
x: .word 0
.end
pc+36의 위치는 0x100c4이다.
저 값이 바로 x가 저장되있는 주소 값이다. 연산 결과를 보면
이런 결과가 나온다는 걸 알 수 있다.
.ltorg
literal pool 프로그램 중간에 정의되는 상수들이 저장되는 장소이다.
만약 mov r0, 0x1234를 할 때,
두 번째 인자 값이 8비트를 넘어버려 명령어 성립이 안 된다.
그렇기 때문에, 레이블을 따로 만들어서
ldr r0, =0x1234(이런 레이블은 없음) 이런 식으로 r0에 값을 넣어야 함
이런 레이블들이 담긴 영역이 .ltorg이다.
ltorg를 풀어 쓰자면 literal origin, literal 영역이 시작되는 곳이다.
간단한 예시를 보자. 코드는 data 섹션에 썻던 그 코드다.
중간에 보면 ldr r4, =0x12345678 이 보인다.
ldr의 offset 값은 8bit 크기인데, 0x12345678은 너무 큰 수다.
그렇기 때문에 이를 따로 저장해야 하는데 그 공간이 .ltorg 이다.
그럼 저게 어떻게 변환되는지를 보자.
_start+32에 bp를 찍고 이 때 =0x12345678의 위치를 확인해보면 다음과 같다.
형광펜 친 순서대로 1234, 5678, 4567, 0x12345678 인 것으로 보아, .ltorg는 data 영역 바로 앞에 저장된다.
Directives for Data
여기에 쓰는게 적절한진 모르겠지만, 변수 초기화하는 부분을 보여줬으니, 겸사겸사 같이 설명
.byte <expression> expression 값으로 초기화. 초기화 크기는 앞에 지정한 자료형에 따른다.
만약 .word 32이면, 0x0032로 초기화 된다.
그리고 위의 표현들을 사용할 때 위에 .align 을 해주는데,
메모리에선 값을 읽을 때, chunk 단위로 읽어야 오버헤드 없이 빠르게 처리가 가능하다.
만약 0x0가 아닌, 0x3부터 저장을 한다면, cpu는 0x0~3과 0x4~0x8 두 개의 chunk를 읽어야 하는 불필요한 연산이
발생하니, 처음부터 해당 크기만큼 0으로 초기화된 chunk에 저장한다.
만약, 데이터 간격을 벌려주고 싶다면,
.skip <byte size>을 해주면 된다. 간단한 예를 들면 다음과 같다.
objdump로 결과를 보면
노란 줄 친 곳이 4byte 크기만큼 skip한 부분이다.
'학교 > 시스템 프로그래밍' 카테고리의 다른 글
Signal (0) | 2020.12.05 |
---|---|
PC, LR, SP (0) | 2020.11.17 |
LDR / STR Indexing (0) | 2020.11.17 |
shift 연산자 (0) | 2020.11.11 |
1. LDR/STR/ADR, 논리 연산 (0) | 2020.11.10 |