crt0.S 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. /* When we enter this piece of code, the program stack looks like this:
  2. argc argument counter (integer)
  3. argv[0] program name (pointer)
  4. argv[1...N] program args (pointers)
  5. argv[argc-1] end of args (integer)
  6. env[0...N] environment variables (pointers)
  7. NULL
  8. When we are done here, we want
  9. a1=argc
  10. a2=argv[0]
  11. a3=argv[argc+1]
  12. This file now uses the register naming from the ARM Procedure Calling Standard
  13. Name Number APCS Role
  14. a1 0 argument 1 / integer result / scratch register / argc
  15. a2 1 argument 2 / scratch register / argv
  16. a3 2 argument 3 / scratch register / envp
  17. a4 3 argument 4 / scratch register
  18. v1 4 register variable
  19. v2 5 register variable
  20. v3 6 register variable
  21. v4 7 register variable
  22. v5 8 register variable
  23. sb/v6 9 static base / register variable
  24. sl/v7 10 stack limit / stack chunk handle / reg. variable
  25. fp 11 frame pointer
  26. ip 12 scratch register / new-sb in inter-link-unit calls
  27. sp 13 lower end of current stack frame
  28. lr 14 link address / scratch register
  29. pc 15 program counter
  30. */
  31. .text
  32. .align 2
  33. .global __environ
  34. .global _start
  35. .global exit
  36. .global main
  37. .global __libc_init
  38. .global __init_stdio
  39. .global __stdio_close_all
  40. .global _void_void_null_func
  41. .type _start,%function
  42. .type exit,%function
  43. .type main,%function
  44. .type __libc_init,%function
  45. .type __init_stdio,%function
  46. .type __stdio_close_all,%function
  47. .type _void_void_null_func,%function
  48. .text
  49. _start:
  50. /* clear the frame pointer */
  51. mov fp, #0
  52. /* Load register a1 (argc) from the stack to its final resting place */
  53. ldr a1, [sp], #4
  54. /* Copy argv pointer into a2 -- which its final resting place */
  55. mov a2, sp
  56. /* Set up environ, skip to the end of argv, and put
  57. * a pointer to whatever we find there (hopefully the
  58. environment) in a3 */
  59. ldr a4, .L3
  60. add a3, a2, a1, lsl #2
  61. add a3, a3, #4
  62. str a3, [a4, #0]
  63. /* Tell libc to initialize whatever it needs */
  64. bl __libc_init
  65. bl __init_stdio
  66. bl main
  67. bl exit
  68. _void_void_null_func:
  69. nop
  70. .weak __libc_init
  71. __libc_init = _void_void_null_func
  72. .weak __init_stdio
  73. __init_stdio = _void_void_null_func
  74. .weak __stdio_close_all
  75. __stdio_close_all = _void_void_null_func
  76. .align 2
  77. .L3:
  78. .word environ
  79. .data
  80. .align 2
  81. .global __environ
  82. __environ:
  83. .long 0
  84. .weak environ
  85. environ = __environ