spaghetti.c 를 Assembly로 만든다는 건, ARM core에서 동작하는 Assembly로 spaghetti.c를 가공하는 일입니다. spaghetti.c를 Assembly로 만드는 일 역시 tcc, armcc가 한꺼번에 알아서 해주니까 해 볼일은 없겠지만, 한번 해보는 것도 의미는 있으리라 생각합니다. - 과연 의미 있을지는 두고 봐야 하겠지요 하하 -
RAM에 아주~ 간단한 ram 상주 프로그램을 올릴 때, 이런 기법이 사용되기도 하니, Software 동작원리 이후에 아주 재미있는 간단한 요리법을 하나 알려드리지요. 잊지 마세요!
Assembly로 만드는 방법은 아주 간단합니다. -S option을 사용하지요
tcc -S spaghetti.c
saghetti.s -------------------------------------------
; generated by Thumb C Compiler, ADS1.2 [Build 805]
; commandline [-O2 -S -IC:\apps\ads12\INCLUDE] CODE16
AREA ||.text||, CODE, READONLY
main PROC
MOV r0,#3
MOV r1,#4
ADD r0,r0,r1
ADD r0,r2,r0
BX lr
DCW 0000
ENDP
AREA ||.bss||, NOINIT, ALIGN=2
||zi||||.bss$7|| % 4
AREA ||.data||, DATA, ALIGN=2
||.data$10||||rw|| DCD 0x00000003
AREA |area_number.1|, DATA, ALIGN=2 EXPORTAS |area_number.1|, ||.data||||.data$15||relocate DCD 0x00000003
EXPORT main EXPORT relocate EXPORT ||rw|| EXPORT ||zi||
IMPORT _main IMPORT __main IMPORT ||Lib$$Request$$armlib||, WEAK
KEEP ||BuildAttributes$$THUMB_ISAv1$M$PE$A:L22$X:L11$S22$~IW$~STKCKD$~SHL$OSPACE$PRES8||||BuildAttributes$$THUMB_ISAv1$M$PE$A:L22$X:L11$S22$~IW$~STKCKD$~SHL$OSPACE$PRES8|| EQU 0
ASSERT {ENDIAN} = "little" ASSERT {SWST} = {FALSE} ASSERT {NOSWST} = {TRUE} ASSERT {INTER} = {FALSE} ASSERT {ROPI} = {FALSE} ASSERT {RWPI} = {FALSE} ASSERT {NOT_SHL} = {TRUE} ASSERT {FULL_IEEE} = {FALSE} ASSERT {SHL1} = {FALSE} ASSERT {SHL2} = {FALSE} END
으악! 간단하다고 하더니, 막상 해보니까, 엄청 긴 파일이 생성이 되어 버렸네요. 하지만, 기죽을 거 없습니다.
다 필요 없는 얘기들이고, spaghetti.c 의 main 함수가 어떻게 컴파일 되었는지 만 확인해 보면 될 것 같습니다. 다른 것들이야 어떻게 되든 말든. 흥.
원래 c로 되어 있는 main 함수
int main () {
int stack; volatile int local,local2,loca3l; local = 3; local2 = 4; local3 = add (local, local2); stack += local3; return stack;
}
Assembly의 main 함수
main PROC
MOV r0,#3 ; r0 = 3 ; local = 3
MOV r1,#4 ; r1 = 4 ; local2 = 4
ADD r0,r0,r1 ; r0=r0+r1 ; local3 = local + local2
ADD r0,r2,r0 ; r0=r2+r0 ; stack = stack + local3
BX lr
DCW 0000
ENDP
참고로 위의 함수 중 main PROC는 main이라는 녀석이 함수라는 뜻이고 그 끝은 ENDP로 표기됩니다.
가만히 보니까 원래 main() 함수하고 비교해 보면, local (r0) = 3, local2 (r1) = 4를 해주고 나서, local3 (r0) 에다가 local (r0) + local2(r1)을 넣어주고, 다시, stack (r0) = stack (r2) + local3 (r0)를 해준다 그게 요점이며, 결국 return 값 r0에다가 stack 값을 넣는 것으로 assembly가 구성되어 있습니다. 일단, main() 함수 중 add (local, local2)에서, 함수를 호출하지 않은 이유는 compiler 입장에서 코드를 잘 훑어 보니, 굳이 함수를 호출할 것이 아니라, "두 개의 인자를 더하는 함수다" 라는 사실을 눈치를 채버려서, compiler가 할 일은 최적화라는 입장을 잊지 않고, 똑같은 효과의 assembly를 만들어 낸 것이지요. Compiler라는 녀석은 상당히 교활한 녀석이면서도 똑똑한 녀석입니다.
댓글