assembly - “在函数调用中保留寄存器”是什么意思?
问题描述
从这个问题, What registers are reserved through a linux x86-64 function call,它说以下寄存器在函数调用中保存:
r12, r13, r14, r15, rbx, rsp, rbp
因此,我继续进行了以下测试:
.globl _start
_start:
mov $5, %r12
mov $5, %r13
mov $5, %r14
mov $5, %r15
call get_array_size
mov $60, %eax
syscall
get_array_size:
mov $0, %r12
mov $0, %r13
mov $0, %r14
mov $0, %r15
ret
而且,我在想,在那之后call get_array_size
,我的寄存器会自动(并且有点神奇地)恢复为 values 5
。gdb
表明这是不正确的。
但我想我可能误解了这一点。我想这只是意味着“符合 x86-64 ABI”的任何函数都应该在完成后恢复这些寄存器(换句话说,我的get_array_size
函数是 linux ABI 中的无效函数),或者有人可以解释一下我在我的理解中似乎缺少什么。
此外,当有人说函数应该符合 时ABI
,非全局函数也应该这样做吗?或者“内部实现”根本不重要,只有我向公众公开的功能(通过globl
)应该遵守它?是否有一种通常用于表示函数是局部函数还是全局函数的符号(例如在命名方案中?)。
当然,我是初学者,asm
非常感谢您解释我可能遗漏的内容。
解决方案
正确,您的手写 asmget_array_size
不遵循 ABI,因为它正在破坏调用保留寄存器。这意味着它的调用者需要特别对待它,而不是遵循通常的 ABI 保证。
ABI 文档是编译器生成的函数遵循的标准,大多数手写函数也应遵循该标准,除非您想制定自己的自定义调用约定。请参阅什么是被调用者和调用者保存的寄存器?有关调用保留与调用破坏对调用者意味着什么的更多详细信息,以及函数本身的实现(如果它想遵循 ABI)。
只要您对它们进行注释(并且永远不要尝试从 C 调用它们),具有自定义调用约定的小型私有“帮助器”函数就可以了。尤其是在优化时,例如代码大小(请参阅codegolf x86-64 提示)
asm 没有魔法,每条指令只对架构状态有其记录的影响。 (寄存器和内存的内容)。
正如您从英特尔的文档中看到的那样call
,ret
他们修改的唯一整数寄存器是 RSP。像 NASM 和 GAS 这样的普通汇编程序不会神奇地向您的函数添加指令。(MASM 可以不同,但是如果你看反汇编你仍然可以看到真正的代码。)
推荐阅读
- javascript - 表格列宽
- javascript - 根据用户事件滚动到行,R/DT/Shiny,不使用分页
- reactjs - react-select 中的 onKeydown 事件
- mysql - 我不能用 lowerCase 执行 Sql UpperCase
- symfony - 在学说或验证中未定义为关联
- winapi - 为什么 C++ 应用程序中的变量地址在 Windows 上不同
- android - 如何让安卓应用支持所有屏幕尺寸?
- javascript - 如何从 AngularJS 中的 url 中删除 # 并使路径在重新加载/刷新时工作?
- python - 使用python修改Excel文件
- javascript - 外部 Js 文件中的一项功能未在 HTMLButtonElement.onclick 中定义