일단 1 키를 누르면 hello world! 뜨게 니 코드 수정해서 working하게 하는 거 성공했다.
하나하나 문제점을 짚어 줄테니 잘 봐라.
1) scan.S의 scan 함수에서 리턴 값을 r0 레지스터에 담아서 보낼 거면서
스택 프레임을 형성하고 해제하는 과정에서 r0 레지스터 값을 백업했다가 복구시킴.
scan
stmfd sp!, {r0, r4-r12, lr}
...
ldmfd sp!, {r0, r4-r12, pc}
그래서 system call (swi) 명령어로 키 입력을 받으면 r0 레지스터에 담기는데
ldmfd 명령 때문에 r0 레지스터 값이 함수 호출 전으로 초기화 되어버림.
그래서 print_helloworld.S의 print_helloworld 함수에서
print_helloworld
...
bl scan
cmp r0, #49
beq print
...
이게 절대 만족하지 않는 거지!
해결하는 방법은 scan 함수에서 stmfd, ldmfd 명령어에서 r0을 모두 지워주면 돼.
2) 여기까지 하면 cmp 문에서 #49 (#0x31 == '1') 와 정상적으로 비교되는 것은 알 수 있는데
무한 루프에 빠진다는 걸 알 수 있어. 그 이유는
beq print
문 때문임. 보아하니 lr 레지스터에 return address가 담기고 pc가 program counter 레지스터로 보이는데,
bl(branch & link) 명령어는 return address를 lr 레지스터에 담아서 branch하는 반면
일반 branch 명령어(b)는 return address를 lr 레지스터에 담지 않는 것으로 보임.
조건이 달려있는 경우도 그래. beq는 return address를 담지 않고 bleq가 return address를 담지.
return address를 담지도 않는데 print 함수 내부에서 lr 값으로 jump 해버리니 계속
아까 bl scan 문에 의해 설정된 lr 값을 써버려서 cmp r0, #49 로의 리턴이 발생한다.
이걸 해결하려면 beq를 bleq로 고쳐야 함.
3) 마지막으로 이렇게 고쳐서 실행해 보면 프로그램은 정상적으로 꺼지는데 화면에 아무것도 출력이 안됨을 알 수 있음.
그 이유는 뻔하지. adr r0, start_print 에서 출력할 문자열을 지시하고 있는데 print 함수가 끝나고 지시하면 어캄.
adr r0, start_print 라인을 bleq 라인 위로 올려준다.
성공!!
r4 에서 r12 까지 쓰고 있는것 같지도 않은데 왜 백업을 하는지 모르겠넹 ㅋㅋ
lr 저장하고 pc 로 백업하고만 하면 될 것 같음.
그러게요 ㄷㄷ 아마도 눈호랑이가 저 코드 라인을 제대로 이해 못하고 그냥 수업 시간에 알려준 코드대로 복사 붙여넣기해서 짠 것으로 보입니다...
형 어샘 잘하세요? 저좀 많이 가르쳐주세요 리버싱 관심 있는데