IA-32和x86-64调用规约

本文概述了x86汇编语言中的寄存器使用规范、函数参数及返回值的传递方式,以及控制寄存器和标志位的管理规则。在函数内部,win32和win64平台下对易变与非易变寄存器的操作有着明确的规定。此外,还详细介绍了函数参数的入栈顺序、不同类型返回值的存放位置等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章总结了编写x86汇编语言必须遵守的一些约定

1、易变(Volatile)和非易变(Non-Volatile)寄存器


表列举了Visual C++易变和非易变寄存器,函数如果要使用非易变寄存器的,那么必须要保存非易变寄存器的内容,win32函数使用push 和 pop 指令来保存非易变通用寄存器的内容,win64函数除了要保存通用非易变寄存器的内容外,还需要保存XMM非易变寄存器。在函数内部,win32和win64均可以无限制的使用易变寄存器。

也就是说:

拿32位汇编程序举例,函数如果使用EBP、EBX、ESI、EDI寄存器那么必须push指令保存寄存器内容,在函数ret指令之前用pop指令恢复寄存器内容。那么反过来,函数在通过call指令调用子函数之前,要保存EAX、ECX、EDX寄存器的内容,其中在子函数的返回值保存在EAX寄存器中。

函数如果使用了MM0~MM7指令必须在ret指令前使用emms指令来复位,因为MM0~MM7寄存器借用浮点寄存器ST(0)~ST(7)的低64位,所以在函数返回之前要恢复浮点寄存器ST中的内容。同样,函数使用YMM寄存器应该在函数ret之前使用vzeroupper指令恢复AVX/SSE寄存器内容。

2、函数参数和返回值

此表总结了函数参数和返回值的调用规约。

以32位汇编为例:

  • 函数参数:调用者负责入栈,参数入栈顺序的采用从右至左
  • 整形数返回值(8bit、16bit、32bit):函数将返回值保存到EAX寄存器中
  • 整形数返回值(64bit):函数将返回值保存到EDX:EAX寄存器
  • 指针返回值:保存到EAX寄存器
  • 浮点数返回值(float、double):保存到ST(0)寄存器中
  • 结构体值返回(1,2,4,8字节):保存带EDX:EAX寄存器中
  • 结构体值返回(其他字节):EBP+8(第一个参数)隐含指针指定结构体内存位置,EAX返回隐藏的指针
  • 栈指针:四字节对齐

值返回超过8字节结构体的函数利用一个隐藏指针,函数将该指正通过EAX返回。例如,函数extern "C" MyStruct Foo(int a,int b)。win32汇编程序可以访问[EBP+8]内存位置的隐含结构体指针,也就是说到[EBP+8]不是参数b,而是一个隐含的结构体指针,所以[EBP+12]的位置为参数b,[EBP+16]的位置为参数a,函数一个隐含的结构如指针通过EAX寄存器返回。

3、控制寄存器和Flags


此表列举了x87寄存器默认的控制字,x86-SSE控制和状态寄存器(MXCSR),和字节方向标志位。所有的控制标志是非易变的,他们的内容必须被调用函数保存。需要使用一个或者更多浮点异常的程序可以使用visual c++库函数_fpieee_flt来自定义浮点异常处理程序。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值