{"action":"created","issue":{"url":"https://api.github.com/repos/go-internals-cn/go-internals/issues/11","repository_url":"https://api.github.com/repos/go-internals-cn/go-internals","labels_url":"https://api.github.com/repos/go-internals-cn/go-internals/issues/11/labels{/name}","comments_url":"https://api.github.com/repos/go-internals-cn/go-internals/issues/11/comments","events_url":"https://api.github.com/repos/go-internals-cn/go-internals/issues/11/events","html_url":"https://github.com/go-internals-cn/go-internals/issues/11","id":339234951,"node_id":"MDU6SXNzdWUzMzkyMzQ5NTE=","number":11,"title":"chapter1","user":{"login":"huangxiaoye","id":1125592,"node_id":"MDQ6VXNlcjExMjU1OTI=","avatar_url":"https://avatars0.githubusercontent.com/u/1125592?v=4","gravatar_id":"","url":"https://api.github.com/users/huangxiaoye","html_url":"https://github.com/huangxiaoye","followers_url":"https://api.github.com/users/huangxiaoye/followers","following_url":"https://api.github.com/users/huangxiaoye/following{/other_user}","gists_url":"https://api.github.com/users/huangxiaoye/gists{/gist_id}","starred_url":"https://api.github.com/users/huangxiaoye/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/huangxiaoye/subscriptions","organizations_url":"https://api.github.com/users/huangxiaoye/orgs","repos_url":"https://api.github.com/users/huangxiaoye/repos","events_url":"https://api.github.com/users/huangxiaoye/events{/privacy}","received_events_url":"https://api.github.com/users/huangxiaoye/received_events","type":"User","site_admin":false},"labels":[{"id":957623907,"node_id":"MDU6TGFiZWw5NTc2MjM5MDc=","url":"https://api.github.com/repos/go-internals-cn/go-internals/labels/question","name":"question","color":"1d76db","default":true}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":4,"created_at":"2018-07-08T15:33:22Z","updated_at":"2018-07-09T03:59:14Z","closed_at":null,"author_association":"NONE","body":"//go:noinline\r\nfunc Add(a, b int32) int32 { return a + b }\r\n\r\ntype Adder struct{ id int32 }\r\n//go:noinline\r\nfunc (adder *Adder) AddPtr(a, b int32) int32 { return a + b }\r\n//go:noinline\r\nfunc (adder Adder) AddVal(a, b int32) int32 { return a + b }\r\n\r\nfunc main() {\r\n    Add(10, 32) // direct call of top-level function\r\n\r\n    adder := Adder{id: 6754}\r\n    adder.AddPtr(10, 32) // direct call of method with pointer receiver\r\n    adder.AddVal(10, 32) // direct call of method with value receiver\r\n\r\n    (&adder).AddVal(10, 32) // implicit dereferencing\r\n}\r\n汇编输出:\r\n0x0000 TEXT\t\"\".main(SB), $40-0\r\n  ;; ...omitted everything but the actual function call...\r\n  0x0021 MOVQ\t$137438953482, AX\r\n  0x002b MOVQ\tAX, (SP)\r\n  0x002f CALL\t\"\".Add(SB)\r\n  ;; ...omitted everything but the actual function call...\r\n\r\n你好，请教个问题。\r\n1) main 函数的栈帧空间为什么是40bytes？我的理解是（64位机器）：\r\n    一个局部变量 addr 4bytes，\r\n    调用函数 Add  2(2*4bytes)个入参和1(1*4btyes)个返回值\r\n    调用 adder. AddPtr 3个入参,1个指针类型 8bytes, 2个int32 (2*4bytes),还有一个返回值4bytes\r\n    总共 4+12+8+8+4=36bytes,内存对齐到 40bytes.\r\n2)adder.AddPtr(10,32), adder.AddVal(10,32),  (&adder).AddVal(10, 32),这三个方法调用，可以看做是一种方法调用，CALLER为这三种调用准备一份参数和返回值。\r\n我的理解是否正确？如果不正确，方便的话请指教，谢谢。"},"comment":{"url":"https://api.github.com/repos/go-internals-cn/go-internals/issues/comments/403353223","html_url":"https://github.com/go-internals-cn/go-internals/issues/11#issuecomment-403353223","issue_url":"https://api.github.com/repos/go-internals-cn/go-internals/issues/11","id":403353223,"node_id":"MDEyOklzc3VlQ29tbWVudDQwMzM1MzIyMw==","user":{"login":"chai2010","id":2295542,"node_id":"MDQ6VXNlcjIyOTU1NDI=","avatar_url":"https://avatars1.githubusercontent.com/u/2295542?v=4","gravatar_id":"","url":"https://api.github.com/users/chai2010","html_url":"https://github.com/chai2010","followers_url":"https://api.github.com/users/chai2010/followers","following_url":"https://api.github.com/users/chai2010/following{/other_user}","gists_url":"https://api.github.com/users/chai2010/gists{/gist_id}","starred_url":"https://api.github.com/users/chai2010/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chai2010/subscriptions","organizations_url":"https://api.github.com/users/chai2010/orgs","repos_url":"https://api.github.com/users/chai2010/repos","events_url":"https://api.github.com/users/chai2010/events{/privacy}","received_events_url":"https://api.github.com/users/chai2010/received_events","type":"User","site_admin":false},"created_at":"2018-07-09T03:59:14Z","updated_at":"2018-07-09T03:59:14Z","author_association":"NONE","body":"Go汇编语言并没有讲述如何处理BP（甚至这个寄存器是可以省略的特性）。我是根据文中生成的代码推测的BP位置。根据以下理由。\r\n\r\n首先这里BP不是从SP开始位置，那么很可能就是在参数和返回值上面的位置：\r\n\r\n```go\r\n  0x0013 MOVQ\t\tBP, 16(SP)\r\n  0x0018 LEAQ\t\t16(SP), BP\r\n```\r\n\r\n这个BP的代码是为了应付调用新函数时覆盖当前的BP，其实只是为了保持当前main函数的BP状态，等被调用函数返回后（BP可能被破坏），再从对应的栈内存恢复。因此如果没有新的函数调用，也就没有必要生成BP相关代码。而局部变量addr是main函数所有的，在没有调用函数之前（此时还没有BP相关的栈空间）就存在。\r\n\r\n第二个问题，需要注意Go汇编代码中的SP和最终生成的代码中的SP也不是完全等价的。细节我也不太了解。可以问问 @cch123 "}}
{"actor":{"display_login":"chai2010"}}