入参传递
当执行可执行程序的时候,经常会在执行命令中携带参数如下所示:
这部分参数是怎样在启动过程中传递的呢?
- 在启动函数
_rt0_amd64中: 
1 2 3 4
   | TEXT _rt0_amd64(SB),NOSPLIT,$-8    MOVQ   0(SP), DI  // argc    LEAQ   8(SP), SI  // argv    JMP    runtime·rt0_go(SB)
   | 
 
将栈上的入参保存到DI和SI寄存器(至于在此之前入参是怎么保存到栈上的不展开说明)。
- 在
rt0_go函数中, 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 	// copy arguments forward on an even stack 	MOVQ	DI, AX		// 拷贝入参argc到AX寄存器 	MOVQ	SI, BX		// 拷贝入参argv到BX寄存器     ...   	MOVQ	AX, 24(SP)  // 将AX值(argc)存入SP+24栈地址上 	MOVQ	BX, 32(SP)  // 将BX值(argv)存入SP+32栈地址上 	... 	MOVL	24(SP), AX		// 将SP+24值(argc)赋值给AX寄存器 	MOVL	AX, 0(SP)       // 将AX值(argc)保存到SP栈地址上 	MOVQ	32(SP), AX		// 将SP+32值(argv)赋值给AX寄存器 	MOVQ	AX, 8(SP)       // 将AX值(argv)保存到SP+8栈地址上     CALL	runtime·args(SB)      // 调用runtime·args函数     CALL	runtime·osinit(SB)    // 调用runtime·osinit函数 	CALL	runtime·schedinit(SB) // 调用runtime·schedinit函数 	...
   | 
 
将入参存入栈SP+0和SP+8地址上(构造栈上的Callee arg),并调用runtime·args函数,将入参保存到全局变量argc和argv上
1 2 3 4 5
   | func args(c int32, v **byte) {    argc = c    argv = v    sysargs(c, v) }
  | 
 
- 在
runtime·schedinit函数中调用goargs()函数,将argv以字符串的形式保存到全局切片变量argslice中。 
1 2 3 4 5 6 7 8 9
   | func goargs() {    if GOOS == "windows" {       return    }    argslice = make([]string, argc)    for i := int32(0); i < argc; i++ {       argslice[i] = gostringnocopy(argv_index(argv, i))    } }
  | 
 
- 在
os包初始化的时候调用runtime_args(即runtime包中os_runtime_args函数),将全局变量argslice拷贝一份赋值给os包全局变量Args 
1 2 3 4 5 6 7 8 9
   | var Args []string
  func init() {    if runtime.GOOS == "windows" {              return    }    Args = runtime_args() }
   | 
 
1 2
   |  func os_runtime_args() []string { return append([]string{}, argslice...) }
 
  | 
 
那么,使用者可以在代码中访问os.Args获得程序入参。