首页 > 其他分享 >x86 常见调用约定(cdecl,fastcall,stdcall) & x86和ARM调用约定的栈帧分析 & ARM ATPCS(ARM-THUMB procedure call standard)

x86 常见调用约定(cdecl,fastcall,stdcall) & x86和ARM调用约定的栈帧分析 & ARM ATPCS(ARM-THUMB procedure call standard)

时间:2023-02-11 17:25:30浏览次数:53  
标签:movl 调用 x86 cfi int pushl eax ebp ARM

PS:要转载请注明出处,本人版权所有。

PS: 这个只是基于《我自己》的理解,

如果和你的原则及想法相冲突,请谅解,勿喷。

前置说明

  本文作为本人csdn blog的主站的备份。(BlogID=053)
  本文发布于 2018-01-18 11:29:39,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=053)

环境说明

  X86:gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.5)

  ARM:gcc version 4.8.3 20131202 (prerelease) (Hisilicon_v400)

前言


  由于某些工作的需要,我需要掌握X86以及ARM的一些调用规则,让自己可以大致看懂ASM代码。于是,我总结了一下我需要的东西。

  调用约定有啥用?

  对于现在习惯使用高级程序的人来说,这一切都是闲的蛋疼才会去看这些,不止浪费时间,还浪费表情。但对于有需求使用ASM+C或者C艹的混合编程或者纯ASM编程的时候,这就得注意这些了。因为这代表着你的目标能否成功的问题。





x86 常见调用以及对应的栈帧分析




cdecl用在C/C++,MFC的默认方式, 可变参数
//cdecl
extern "C"
int __attribute__((cdecl)) Func2(int a, int b, int c, int d, int e, int f){

	
	int aa;
	int bb;
	int cc;
	int dd;
	
	aa = bb = cc= dd = a;	

	return 0;
}
@调用子程序过程
	pushl	$6
	pushl	$5
	pushl	$4
	pushl	$3
	pushl	$2
	pushl	$1
	call	Func2
	@call,eip入栈,跳转到子程序
	addl	$24, %esp
	@esp-24,清空临时栈
@子程序过程
.LFE1021:
	.size	Func1, .-Func1
	.globl	Func2
	.type	Func2, @function
Func2:
.LFB1022:
	.cfi_startproc
	pushl	%ebp
	@ebp入栈
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	@esp赋值给ebp
	.cfi_def_cfa_register 5
	subl	$16, %esp
	@注意,虽然上面esp减16是由于有4个4byte的局部变量,但是如果不是4个局部变量,此版本的编译器是按照16byte*N(N取大于0的整数)来分配的局部栈。列如:3个4byte变量,局部栈大小是16bytes,5个4byte变量,局部栈大小为32bytes,其他类似方式分配,不要看不懂为啥多分配了,或者少分配了。
	movl	8(%ebp), %eax
	@a 赋值给eax
	movl	%eax, -16(%ebp)
	@ eax 赋值给dd
	movl	-16(%ebp), %eax
	movl	%eax, -12(%ebp)
	movl	-12(%ebp), %eax
	movl	%eax, -8(%ebp)
	movl	-8(%ebp), %eax
	movl	%eax, -4(%ebp)
	movl	$0, %eax
	@返回值放在eax
	leave
	@leave = mov ebp,esp 以及 pop ebp
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	@pop eip
	.cfi_endproc

  说明:按从右至左的顺序压参数入栈,由调用者把参数弹出栈。

  对子程序分析:其他详见注释。具体栈帧分布图,见下图:

rep_img


stdcall,Win API
extern "C"
int __attribute__((stdcall)) Func3(int a, int b, int c, int d, int e, int f){
	
	int aa;
	int bb;
	int cc;

	aa = bb = cc;		
	
	return 0;
}

	pushl	$6
	pushl	$5
	pushl	$4
	pushl	$3
	pushl	$2
	pushl	$1
	call	Func3
.LFE1022:
	.size	Func2, .-Func2
	.globl	Func3
	.type	Func3, @function
Func3:
.LFB1023:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$16, %esp
	movl	-12(%ebp), %eax
	movl	%eax, -8(%ebp)
	movl	-8(%ebp), %eax
	movl	%eax, -4(%ebp)
	movl	$0, %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret	$24
	@pop eip , subl 24,esp
	.cfi_endproc

  说明:按从右至左的顺序压参数入栈,由被调用者从栈中弹出参数。

  其他参考见上文。



fastcall,要求速度快
extern "C"
int __attribute__((fastcall)) Func4(int a, int b, int c, int d, int e, int f){
	
	int aa;
	int bb;
	int cc;

	aa = bb = cc;	

	return 0;
}
	pushl	$6
	pushl	$5
	pushl	$4
	pushl	$3
	movl	$2, %edx
	movl	$1, %ecx
	call	Func4
.LFE1023:
	.size	Func3, .-Func3
	.globl	Func4
	.type	Func4, @function
Func4:
.LFB1024:
	.cfi_startproc
	pushl	%ebp
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp
	.cfi_def_cfa_register 5
	subl	$24, %esp
	movl	%ecx, -20(%ebp)
	movl	%edx, -24(%ebp)
	movl	-12(%ebp), %eax
	movl	%eax, -8(%ebp)
	movl	-8(%ebp), %eax
	movl	%eax, -4(%ebp)
	movl	$0, %eax
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret	$16
	.cfi_endproc

  说明:按从右至左的顺序压参数入栈,参数1,参数2通过ecx,edx传递,由被调用者从栈中弹出参数。

  其他参考见上文。





ARM ATPCS


extern "C"
int Func1(int a, int b, int c, int d, int e, int f){
	
	int aa;
	int bb;
	int cc;
	int dd;
	int ee;
	
	aa = bb = cc= dd = ee = a;	

	return 0;
}
	mov	r3, #5
	str	r3, [sp]
	mov	r3, #6
	str	r3, [sp, #4]
	mov	r0, #1
	mov	r1, #2
	mov	r2, #3
	mov	r3, #4
	bl	Func1
	.text
	.align	2
	.global	Func1
	.type	Func1, %function
Func1:
	.fnstart
.LFB971:
	@ args = 8, pretend = 0, frame = 40
	@ frame_needed = 1, uses_anonymous_args = 0
	@ link register save eliminated.
	str	fp, [sp, #-4]!
	add	fp, sp, #0
	sub	sp, sp, #44
	str	r0, [fp, #-32]
	str	r1, [fp, #-36]
	str	r2, [fp, #-40]
	str	r3, [fp, #-44]
	ldr	r3, [fp, #-32]
	str	r3, [fp, #-8]
	ldr	r3, [fp, #-8]
	str	r3, [fp, #-12]
	ldr	r3, [fp, #-12]
	str	r3, [fp, #-16]
	ldr	r3, [fp, #-16]
	str	r3, [fp, #-20]
	ldr	r3, [fp, #-20]
	str	r3, [fp, #-24]
	mov	r3, #0
	mov	r0, r3
	sub	sp, fp, #0
	@ sp needed
	ldr	fp, [sp], #4
	bx	lr
	.cantunwind
	.fnend

  分析:

  • r15 PC The Program Counter.

  • r14 LR The Link Register.

  • r13 SP The Stack Pointer.

  • r12 IP The Intra-Procedure-call scratch register. (可简单的认为暂存SP)

  • R11 可选,被称为FP,即frame pointer。

  其他分析见下图:

rep_img

特别说明:此图保留区域写错了,对于此编译器来说,应该是4个4bytes*N(N大于0的整数)的分配本地变量的方式





后记


  无

参考文献




打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
qrc_img

PS: 请尊重原创,不喜勿喷。

PS: 要转载请注明出处,本人版权所有。

PS: 有问题请留言,看到后我会第一时间回复。

标签:movl,调用,x86,cfi,int,pushl,eax,ebp,ARM
From: https://www.cnblogs.com/Iflyinsky/p/17112127.html

相关文章

  • GCC&&G++ C && C++ 内嵌汇编和调用汇编函数的方法(x86,ARM自己对照改)
    PS:要转载请注明出处,本人版权所有。PS:这个只是基于《我自己》的理解,如果和你的原则及想法相冲突,请谅解,勿喷。前置说明  本文作为本人csdnblog的主站的备份。(BlogID......
  • c++ 调用第三orm框架matador的方法通过vs2019
    1.安装matador编译好window版安装包,在安装目录下复制include和lib文件夹到自己的项目目录一下2.自己的mfc目录如图所示,粘贴制include和lib文件夹 3.用vs2019打开自己......
  • 前端-vue基础90-接口调用async/await
     ......
  • Arm-Linux子系统的互相Notify
    前言:Linux下面不同的子系统一个个的组成了整个系统的运行环节,为了让这些子系统能够互相通讯,有一种叫做:notifychain(通知链)的东西。本篇看下。概括所谓通知链,有通知,......
  • 微信 API 中调用客服消息接口提示错误返回限制
    错误的信息如下:errcode=45015,errmsg=responseoutoftimelimitorsubscriptioniscanceledrid:5f8fd8b7-0f8aa1a9-4b6215a5微信的文档看着这微信不清不楚的文......
  • ARM linux 系统调用实现原理
    https://blog.csdn.net/u013836909/article/details/120962422 LinuxARM系统调用过程分析(一)——Linux编程中的API函数和系统调用的关系LinuxARM系统调用过程分析(二......
  • c语言中调用sve函数的例子
    c语言中调用sve函数(ArmCLanguageExtensionsforSVE)PDFsve.c#include<arm_sve.h>#include<stdio.h>#include<stdlib.h>#include<time.h>#defineARRAYSIZE......
  • RestTemplate调用天地图api
    代码ClientHttpRequestFactoryrequestFactory=newHttpComponentsClientHttpRequestFactory(HttpClients.createDefault());RestTemplateclient=newRest......
  • Feign远程调用 (介绍与使用)
    Feign远程调用Feign是代替RestTemplate进行远程调用的组件,避免了RestTemplate手写复杂的url容易出错的问题,并提高代码的可读性使用Feign步骤1)引入依赖哪个服务要发送远......
  • Java使用代码调用接口http根据ip访问
    HttpClient的主要功能:实现了所有HTTP的方法(GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS等)支持HTTPS协议支持代理服务器(Nginx等)等支持自动(跳转)转向详细使用示例声......