summaryrefslogtreecommitdiff
path: root/rt/start-linux.s
blob: 717d00ff9f543007764a9e94e017485b44b7c8fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
.data
/* std._environment : byte[:][:] */
.globl std$_environment
std$_environment:
.envbase:
.quad 0 /* env size */
.envlen:
.quad 0 /* env ptr */

.globl std$__cenvp
std$__cenvp:
.quad 0

.text
/*
 * The entry point for the whole program.
 * This is called by the OS. In order, it:
 *  - Sets up all argc entries as slices
 *  - Sets up all envp entries as slices
 *  - Converts argc/argv to a slice
 *  - Stashes envp in std._environment
 *  - Stashes a raw envp copy in __cenvp (for syscalls to use)
 *  - Calls main()
 */
.globl _start
_start:
	/* turn args into a slice */
	movq	%rsp,%rbp

	/* stack allocate sizeof(byte[:])*(argc + len(envp)) */
	movq	(%rbp),%rax
	leaq	16(%rbp,%rax,8), %rbx	/* argp = argv + 8*argc + 8 */
        call    count
	addq	%r9,%rax
	imulq	$16,%rax
	subq	%rax,%rsp
	movq	%rsp, %rdx	/* saved args[:] */

	/* stack allocate sizeof(byte[:])*(argc + len(envp)) */
	movq	(%rbp),%rax
	leaq	16(%rbp,%rax,8), %rbx	/* argp = argv + 8*argc + 8 */
        call    count
	addq	%r9,%rax
	imulq	$16,%rax
	subq	%rax,%rsp
	movq	%rsp, %rdx	/* saved args[:] */

	/* convert envp to byte[:][:] for std._environment */
	movq	(%rbp),%rax
	leaq	16(%rbp,%rax,8), %rbx	/* envp = argv + 8*argc + 8 */
        /* store envp for some syscalls to use without converting */
        movq    %rbx,std$__cenvp(%rip)
	movq	%r9,%rax
	movq	%rsp, %rcx
	movq	%r9,.envlen
	movq	%rdx,.envbase
	call cvt
	movq	%rcx,%rdx

        /* convert argc, argv to byte[:][:] for args. */
	movq	(%rbp), %rax	/* argc */
	leaq	8(%rbp), %rbx	/* argv */
	movq	(%rbp), %rsi	/* saved argc */
        call cvt
	pushq %rsi
	pushq %rdx

	/* enter the main program */
	call	main
	/* exit(0) */
        xorq	%rdi,%rdi
	movq	$60,%rax
	syscall