x64调用约定下Clang生成汇编的mov ebx,edi指令作用疑问
问题解答
首先纠正你对x64调用约定的认知偏差:主流x64 System V调用约定中,第一个整型入参通过rdi寄存器传递,rax寄存器仅用于存放函数返回值,你提到的「foo的入参x放在RAX/EAX寄存器中」是错误的。
两个问题的具体解答:
bar的返回值不会存入EBX
bar的返回值遵循调用约定存在eax寄存器中:call bar执行完成后,eax里存储的就是bar(x)的返回值。汇编里的or eax, ebx是将bar的返回值(eax)和foo的入参x(ebx)做按位或运算,效果等价于判断x || b是否为真:只要两个值有一个非0,或运算结果就非0,对应逻辑或条件成立。mov ebx, edi的作用- 首先
edi是rdi的低32位,存储的是foo的第一个整型入参x。 rbx属于被调用者保存寄存器:如果foo内部要修改rbx的值,必须先备份原值,函数返回前恢复,这也是开头push rbx、结尾pop rbx的来源。- 调用
bar时,bar内部可能会覆盖rdi等调用者保存寄存器,所以编译器提前把x的值存到不会被bar修改的ebx里,方便调用完bar后还能拿到原始的x值做后续运算。
- 首先
完整汇编逐行对应逻辑:
foo: # @foo push rbx # 备份rbx原值,符合调用约定 mov ebx, edi # 把入参x存到ebx,避免被bar覆盖 call bar # 调用bar(x),返回值存在eax中 or eax, ebx # 计算x | b,等价于判断x || b是否成立 mov ecx, 456 # 准备条件不成立时的返回值 mov eax, 123 # 准备条件成立时的返回值 cmove eax, ecx # 若or结果为0(x和b都为0,条件不成立),将返回值设为456 pop rbx # 恢复rbx原值 ret # 返回,返回值存在eax中
内容的提问来源于stack exchange,提问作者Charles Nicholson
相关产品推荐
相关产品推荐

