这个程序集如何函数 return 一个值?

How does this assembly function return a value?

我用 C 编写了一个非常简单的函数,它使用 strlen()<string.h> 到 return char* 变量的长度:

int length(char *str) {

    return strlen(str);
}

这是来自 objdump -M intel -d a.out 的相应 x86_64 程序集:

00000000000011a8 <length>:
    11a8:   f3 0f 1e fa             endbr64 
    11ac:   55                      push   rbp
    11ad:   48 89 e5                mov    rbp,rsp
    11b0:   48 83 ec 10             sub    rsp,0x10
    11b4:   48 89 7d f8             mov    QWORD PTR [rbp-0x8],rdi
    11b8:   48 8b 45 f8             mov    rax,QWORD PTR [rbp-0x8]
    11bc:   48 89 c7                mov    rdi,rax
    11bf:   e8 ac fe ff ff          call   1070 <strlen@plt>
    11c4:   c9                      leave  
    11c5:   c3                      ret 

这是我目前对代码的理解(如有不妥请指正):

00000000000011a8 <length>:
    11a8:   f3 0f 1e fa             endbr64 
    11ac:   55                      push   rbp  // stack setup, old rbp of previous frame pushed
    11ad:   48 89 e5                mov    rbp,rsp // rbp and rsp point to same place
    11b0:   48 83 ec 10             sub    rsp,0x10 // space is made for arguments
    11b4:   48 89 7d f8             mov    QWORD PTR [rbp-0x8],rdi // rdi stores argument and is moved into the space made on the line 11b0
    11b8:   48 8b 45 f8             mov    rax,QWORD PTR [rbp-0x8] // value at memory address rbp-0x8 aka argument is stored in rax
    11bc:   48 89 c7                mov    rdi,rax // move the value into rdi for function call
    11bf:   e8 ac fe ff ff          call   1070 <strlen@plt> // strlen() is called
    11c4:   c9                      leave  // stack clear up
    11c5:   c3                      ret // return address popped and control flow resumes

如果上面有什么不正确的地方请指正,其次call 1070 <strlen@plt> return如何取值?因为 strlen() 函数 return 是一个字符串的长度,我本以为有些东西会被移到 rax 寄存器中(我相信它通常用于 return 值).但是没有任何内容被移入 rax 并且它没有在程序集中显示 returned 的值。

最后是地址 1070 处的代码(来自调用 1070 strlen@plt)

0000000000001070 <strlen@plt>:
    1070:   f3 0f 1e fa             endbr64 
    1074:   f2 ff 25 45 2f 00 00    bnd jmp QWORD PTR [rip+0x2f45]        # 3fc0 <strlen@GLIBC_2.2.5>
    107b:   0f 1f 44 00 00          nop    DWORD PTR [rax+rax*1+0x0]

how does call 1070 strlen@plt return a value?

strlen 将其结果放入 rax 寄存器,这也是您的 length() 函数应该将 its return值。

在优化下,您的 length() 可以编译成一条指令:jmp strlen -- 参数已经在 rdi 中,而 return 值将在rax.

P.S.

Lastly here is the code at address 1070

那不是 strlen 的实际代码。这是一个“PLT 跳转存根”。要了解那是什么,您可以阅读 this blog post.

此外,从那个小地址,你可以看出这是一个 PIE 可执行文件:这些只是相对于图像基地址的偏移量;运行时地址类似于 0x55...