장소 : 단국대 제2공학관 (3PM ~ 11PM)
인원 : 공욱학 님 외 12명
진도 : 리눅스 커널 내부구조 끝 (~ Chapter 9), ARM System Developer's Guide 시작 (~P75)
스터디 중 질문 내용 (ARM/Linux)
- 프로시져(서브루틴) 호출시, return 후 돌아가야 하는 주소는 어떻게 저장되는지?
- idle 상태(?)에서 cpu는 어떻게 동작하는지?
- interrup 발생시 cpu의 mode는 어떻게 되는지?
- 고급 언어에서 나눗셈 연산은, 컴파일시 어떻게 명령어로 번역되는지?
스터디 운영 관련
- 4주차 참석 여부 갱신해주세요 : https://docs.google.com/spreadsheets/d/1QteLbtnsuW9J-SkTv0BqNKOnWtq1n3FR9R0fc42sHoc/edit#gid=0
- 향후 스터디는 특별한 이슈 없으면 죽전캠퍼스에서 강의실 빌려서 진행 예정입니다.
- 단대 강의실 사용 전제 하에, 교통편 문제로 인해 스터디 시간 조정이 필요하다는 의견이 있습니다. 이 부분에 대해 주중에 스터디 팀원 의견 취합하여, 필요시 시작 시작을 조정하고자 합니다. 하기 3개 안 중에 택1 하면 어떨까 합니다.
1. 15:00 ~ 23:00 (현행 유지)
2. 14:00 ~ 22:00 (1시간 앞으로 당김)
3. 14:30 ~ 22:30 (중간값)
아키 교재 관련
- ARM System Developer's Guide가 너무 오래되어서 코드 분석을 위해 필요한 지식을 갖추는데에 충분치 않다는 의견이 있습니다. (백창우 님) 스터디 시간 조정 건과 동일하게 스터디 팀원 분들의 중지를 모아 추가 공부 방안을 결정하면 어떨까 합니다. 하기 3개 안 중에 택1하면 어떨까 합니다.
1. ARM System Developer's Guide만 보고 코드 분석 시작, 필요한 건 그때그때 ARM 관련 문서 찾아보기 (현행 유지)
2. ARMv8 (최신 64bit 아키텍쳐) 아키텍쳐 매뉴얼, 프로그래밍 가이드 등 1회 숙독 후 코드 분석 시작
3. ARMv7 (CA7 칩의 아키텍쳐) 아키텍쳐 매뉴얼, 프로그래밍 가이드 등 1회 숙독 후 코드 분석 시작
댓글 7
-
송원식
2017.05.28 22:11
-
목태양
2017.05.30 16:27
SUBS PC, LR and related instructions (ARM)
The SUBS PC, LR, #<const> instruction provides an exception return without the use of the stack. It subtracts the immediate constant from LR, branches to the resulting address, and also copies the SPSR to the CPSR. The ARM instruction set contains similar instructions based on other data-processing operations, or with a wider range of operands, or both. ARM deprecates using these other instructions, except for MOVS PC, LR. -
송원식
2017.05.28 22:13
고급 언어에서 나눗셈 연산은, 컴파일시 어떻게 명령어로 번역되는지?
linux 나누기 코드 확인
확인 결과 arm에서 제공하는 라이브러리의 __aeabi_idiv 함수를 호출하도록 컴파일확인 방법
1) 코드 작성 (test.c)#include <stdio.h>
int div(int a, int b)
{
return a/b;
}
int main(void)
{
int a =10;
int b=2;
int c;
printf("result %d\n", div(a,b) );return 0;
}2) arm 용으로 컴파일
arm-linux-gnueabihf-gcc -S -c test.c3) 어셈코드 확인
div:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
stmfd sp!, {fp, lr}
add fp, sp, #4
sub sp, sp, #8
str r0, [fp, #-8]
str r1, [fp, #-12]
ldr r0, [fp, #-8]
ldr r1, [fp, #-12]
bl __aeabi_idiv
mov r3, r0
mov r0, r3
sub sp, fp, #4
@ sp needed
ldmfd sp!, {fp, pc}
.size div, .-div
.section .rodata
.align 2 -
목태양
2017.05.30 14:19
동일한 코드를 ca15 cpu 타겟으로 컴파일 해보면 아래와 같은 결과물이 나옵니다.
div:
.fnstart
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
.save {fp}
str fp, [sp, #-4]!
.setfp fp, sp, #0
add fp, sp, #0
.pad #12
sub sp, sp, #12
str r0, [fp, #-8]
str r1, [fp, #-12]
ldr r2, [fp, #-8]
ldr r3, [fp, #-12]
sdiv r3, r2, r3
mov r0, r3
sub sp, fp, #0
@ sp needed
ldr fp, [sp], #4
bx lr
.fnend
.size div, .-div
.section .rodata
.align 2sdiv는 ARMv7 ISA의 signed divide 명령어입니다. 머신 옵션이 무엇이냐에 따라(타겟 칩셋에 sdiv 구현되어 있냐에 따라) __aeabi_idiv 함수로 번역되기도 하고, sdiv 명령어로 번역되기도 하는 듯 하네요.. 참고로 ARMv7 아키텍쳐 매뉴얼 상에 나와있는, 나누기 연산에 대한 요구사항은 아래와 같습니다.
ARMv7 implementation requirements and options for the divide instructions
Any implementation of the ARMv7-R profile must include the SDIV and UDIV instructions in the Thumb instruction set.
Any implementation of the Virtualization Extensions must include the SDIV and UDIV instructions in the Thumb and ARM instruction sets.
In the ARMv7-R profile, the implementation of SDIV and UDIV in the ARM instruction set is OPTIONAL.
In an ARMv7-A implementation that does not include the Virtualization Extensions, the implementation of SDIV and UDIV in both instruction sets is OPTIONAL, but the architecture permits an ARMv7-A implementation to not implement SDIV and UDIV. -
송원식
2017.05.28 23:08
개인적으로 아키교재 관련해서는 저는 1번(1. ARM System Developer's Guide만 보고 코드 분석 시작, 필요한 건 그때그때 ARM 관련 문서 찾아보기 (현행 유지)) 을 선호 합니다.
-
목태양
2017.05.30 16:03
- idle 상태(?)에서 cpu는 어떻게 동작하는지?
이 질문에 대한 답변으로 아래 링크 참조해주세요.. 스터디 중에 잠시 언급된 cpu를 정지시키는 명령어(x86의 HLT)에 대한 설명도 있네요..
https://unix.stackexchange.com/questions/361245/what-does-an-idle-cpu-process-do
-
호랑키
2017.06.03 00:35
- 프로시져(서브루틴) 호출시, return 후 돌아가야 하는 주소는 어떻게 저장되는지?
질문에 대한 답변은 아래 링크를 참조해 주시기 바랍니다.
http://recipes.egloos.com/5060815
기본적으로 x86에서는 call 실행후 복귀 하기위한 ret 명령어가 존재하지만,
arm에서는 ret 명령어가 존재하지 않으며, 이를 대체하기 위한 방식으로 link register 라 불리는 r14 특수목적 레지스터가 사용됩니다.
r14 레지스터의 경우 기본적으로 예외 발생이나 인터럽트 처리시 자동으로 복귀주소를 저장하게 되며, bl 계통의 명령어 실행시에도 자동으로 저장됩니다. 재귀함수를 어셈블리어로 변환하여 확인하게 되면 bl 를 실행하는 순간 hardware 적으로 자동으로 복귀주소를 r14 레지스터에 저장하며,
이 값을 스택에 저장하는 과정이 존재하는 것을 확인 하였습니다.
복귀시 pc 에 직접 r14 값을 스택으로 부터 꺼내어 mov 명령어로 복귀주소로 점프하도록 되어 있습니다.
송원식님의 덧글 기준으로 div 함수를 어셈블리어로 변환한 코드중
div:
stmfd sp!, {fp, lr}
...
ldmfd sp!, {fp, pc}
이 부분에서 r14(lr) 값을 system stack 에 저장 후 복귀시 system stack의 복귀주소를 직접 program counter 에 써 넣어 복귀 하는 것을 볼 수 있습니다.
결론 : x86 이나 arm 이나 함수 호출 시 system stack 에 복귀 주소를 저장하는 것은 동일하나 이를 별도의 instruction으로 제공하는지 안하는지의 차이
.
- interrup 발생시 cpu의 mode는 어떻게 되는지?
linux커널에서는 유저와 커널 모드만 존재해서 arm에서 irq, exception모드 등은 svc 모드로 이동해서 처리합니다.
즉 irq 모드에서 svc 모드로 전환해서 처리하게 됩니다.
관련 코드는 아래와 같고 실제 방법은 spsr을 svc모드로 변경하고 movs pc, lr 명령어를 실행하면(lr에는 인터럽트 핸들러 주소가 들어 있음) svc 모드로 변경이 되면서 분기하게 됩니다.
( pc값을 변경 할 때 명령어에 S덧붙임 명령어가 있어서 분기하면서 CPSR에 SPSR을 넣어 복구 즉 SVC 모드로 변경 되면서 리턴됨)
파일: arch\arm\kernel\entry-arm.S
vector_\nam: => vector_irq: macro여서 실제코드는 아래와 같이 치환됨
vector_irq(vector_\nam) :
{중략}
mrs r0, cpsr
eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
msr spsr_cxsf, r0 => 이전 상태를 SVC mode로 바꾼다
{중략}
movs pc, lr @ branch to handler in SVC mode
명령어에 S덧붙임 명령어가 있어서 분기하면서 CPSR에 SPSR을 넣어 복구 즉 SVC 모드로 변경 되면서 리턴됨
ENDPROC(vector_\name)