안녕하세요~
ARM어셈블러를 공부하고 실제로 어떻게 되어있는지 알아볼려는데요...
책에서 이해한걸 바로 적용을 할려니 이해가 안되는 부분이 있어서 질문좀 드립니다...
너무 쉬운 코드인데 이해를 못해서 조금 부끄럽네요..
ARM Assembler공부를 해볼려고 아래의 C코드를 so 라이브러리 형태로 빌드한후에 해당 so파일을 IDA라는 disassembler툴로 열어보았습니다.
코드는 아래와 같습니다.
* C코드
void Java_org_androidtown_thread_SampleThreadActivity_hello(JNIEnv *env, jobject thiz)
{
__android_log_print(ANDROID_LOG_ERROR, "Hello", "Hello Jni World %s : %d", __FILE__, __LINE__);
}
* ASM코드
.text:00000C0C PUSH {R0-R2,LR}
.text:00000C0E MOVS R0, #8
.text:00000C10 LDR R1, =(aHello - 0xC1A)
.text:00000C12 LDR R2, =(aHelloJniWorldS - 0xC1E)
.text:00000C14 LDR R3, =(aJniHello_c - 0xC20)
.text:00000C16 ADD R1, PC ; "Hello"
.text:00000C18 STR R0, [SP,#0x10+var_10]
.text:00000C1A ADD R2, PC ; "Hello Jni World %s : %d"
.text:00000C1C ADD R3, PC ; "jni/hello.c"
.text:00000C1E MOVS R0, #6
.text:00000C20 BLX __android_log_print
.text:00000C24 POP {R1-R3,PC}
위의 어셈코드에서 R1 ~ R3레지스터에 Argument값을 넣어서 __android_log_print 함수를 호출하는 과정인데요
1. ADD R1, PC ---> 이 코드가 이해가 되질 않습니다. PC값을 더해서 R1에 또 왜 넣는건지?
R2, R3도 마찬가지로 밑에 연산이 들어갑니다.
2. MOVS R0, #6 ---> 이 코드의 의미를 잘 모르겠네요...R0레지스터에 왜 6을 넣고 CPSR을 업데이트 하라는건지?
혹시 아시는분 있으시면 답변 좀 부탁드립니다.
댓글 3
-
박한범
2014.08.13 09:51
-
최형호
2014.08.16 19:19
안녕하세요
일반적으로 인자에 값이 하드코딩된 문자열이거나 printf의 format들은 컴파일러에 의해 해당 함수의 마지막에 ro data로 배치됩니다. 즉, 위 예에서 hello나 hello jni world로 구성된 포맷, 그리고 파일명은 해당 함수의 어셈코드 밑에 ro data 로 배치됩니다. 그래서 __android_log_print의 인자로 넘길때 현재 pc 값 기준으로 정해진 offset값을 더해서 읽어오는 것입니다.
그리고 첫번째 인자는 아마 enum값일텐데요 ANDROID_LOG_ERROR 이값이 6일거라 생각됩니다.
수고하세요 -
빈즈파덜
2014.08.18 13:30
두분 모두 친절한 답변에 감사드립니다. ARM어셈블러 수업을 들어서 어셈을 볼줄 안다고 생각했는데 제 착각이였네요~ 다시 기본부터 공부해야겠습니다~^^
.
어셈블리어는 이해하는게 아닌거 같습니다만...?
이미 기계어이고 바로 수행되는 코드이기 때문에 받아들이는 법을 익히시는게 좋습니다.
1. r1, r2, r3에는 __android_log_print를 호출하는 인자들의 주소를 불러옵니다.
근데 이 주소가 pc주소 기반으로 코드에 박혀있기 때문에 위의 코드가 생성된겁니다.
2. 마찬가지로 __android_log_print호출용 상수 인자입니다.
기본부터 공부하셔야겠네요. 그냥 암 어셈블리를 공부하세요.
리버싱은 시스템에 대해 어느정도 이해 없으면 삽질입니다.