KDevelop下面的内联汇编问题

coolFly19 2008-10-23 09:39:14
全局的函数调用,不管是cdecl,stdcall还是fastcall, 其在将参数压栈时都是没有额外的开销的,为什么类成员函数就会多出一个0xc字节开销呢?如下:
sub 0xc, %esp(问题所在,为什么需要这个调用)
push $1
push $2
push 0xabcdef12(this参数)
call function
.
.
.
有哪位知道为什么啊,如果能提供一点联接信息也非常感激。
...全文
117 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
coolFly19 2008-10-31
  • 打赏
  • 举报
回复
结贴!哎!~
coolFly19 2008-10-28
  • 打赏
  • 举报
回复
嗯,我再看看去。。。
coolFly19 2008-10-28
  • 打赏
  • 举报
回复
我使用宏定义:#define fastcall __attribute((regparm(3)))。
coolFly19 2008-10-28
  • 打赏
  • 举报
回复
接着前面继续说,
Dog b;
b.draw_fastcall( 0, 2, 4, 8 );
================
0x08048b7a <main+434>: sub $0x8,%esp
0x08048b7d <main+437>: lea 0xffffffc8(%ebp),%eax
0x08048b80 <main+440>: push $0x8
0x08048b82 <main+442>: push $0x4
0x08048b84 <main+444>: mov $0x2,%ecx
0x08048b89 <main+449>: mov $0x0,%edx
0x08048b8e <main+454>: call 0x8048cf8 <Dog::draw_fastcall(int, int, int, int)>
0x08048b93 <main+459>: add $0x10,%esp
================
除了函数在调用前参数压栈外,还有一些额外的开销,如下:
0x08048b35 <main+365>: sub $0xc,%esp // for thiscall
0x08048b7a <main+434>: sub $0x8,%esp // for fastcall
this_call也就是没有任何关键字的类成员函数,其和有fastcall关键字的draw_fastcall使用的额外开销也是不一样的,

全局cdecl,stdcall函数是没有这个开销的,而全局的fastcall那个函数之所以在跳转进函数之前还要调用:
0x08048ab9 <main+241>: sub $0xc,%,
是因为编译器除了把参数分别送到3个寄存器外,还是给这3个参数分配了栈空间,其实就相当于占位符了,
jerryxiong 2008-10-28
  • 打赏
  • 举报
回复
up
coolFly19 2008-10-28
  • 打赏
  • 举报
回复
这是类成员函数的调用,分别是无关键字和fastcall调用方式的参数压栈:
Dog b;
b.draw_thiscall( 0, 2, 4, 8 );
================
0x08048b35 <main+365>: sub $0xc,%esp
0x08048b38 <main+368>: push $0x8
0x08048b3a <main+370>: push $0x4
0x08048b3c <main+372>: push $0x2
0x08048b3e <main+374>: push $0x0
0x08048b40 <main+376>: lea 0xffffffc8(%ebp),%eax
0x08048b43 <main+379>: push %eax
0x08048b44 <main+380>: call 0x8048d24 <Dog::draw_thiscall(int, int, int, int)>
0x08048b49 <main+385>: add $0x20,%esp
================
coolFly19 2008-10-28
  • 打赏
  • 举报
回复
我用的KDevelop得到的反汇编,因为有界面,似乎调试方便点,这是非类函数的调用:
int f = 0;
f = calc_multi_fastcall_int_3( 1, 2, 3, 4 );
反汇编的结果如下:
0x08048a8c <main+196>: movl $0x0,0xffffffec(%ebp)
0x08048ab9 <main+241>: sub $0xc,%esp
0x08048a96 <main+206>: push $0x4
0x08048a98 <main+208>: mov $0x3,%ecx
0x08048a9d <main+213>: mov $0x2,%edx
0x08048aa2 <main+218>: mov $0x1,%eax
0x08048aa7 <main+223>: call 0x804895c <calc_multi_fastcall_int_3(int, int, int, int)>
0x08048aac <main+228>: add $0x10,%esp
0x08048aaf <main+231>: mov %eax,0xffffffec(%ebp)
archim 2008-10-27
  • 打赏
  • 举报
回复
你用的g++是什么版本的?

老实说我很怀疑g++会产生这样的代码
不过我倒是见过这样的
sub 0xc, %esp(问题所在,为什么需要这个调用)
movl $1, 0(%esp)
movl $2, 4(%esp)
movl $0xabcdef12, 8(%esp)
call function

即直接用movl修改栈里面的参数,而不是用pushl压栈
coolFly19 2008-10-27
  • 打赏
  • 举报
回复
我刚接触Linux不久,对其上面使用的编译器也不甚了解,还希望哪位高抬贵手,能说明下原因或者告诉我相关文档,我都给分,同时也不胜感激!
coolFly19 2008-10-27
  • 打赏
  • 举报
回复
我就举个例子,
class A
{
public:
A() {}
~A() {}

int move( int offset )
{
retun offset;//为了说明问题,简单返回
}
};
在代码中如下调用:
A tom;
tom.move( 1 );
KDevelop的反汇编大致如下:
subl $0xc, %esp;
pushl $0x1;
lea tom, %eax;//原文不是这样,这里做了简化,就是取tom的地址
pushl %eax;
call address of function 'move'
addl $0x10, %esp;

事实上,在Windows上使用VS是没有 subl $0xc, %esp; 的。
coolFly19 2008-10-27
  • 打赏
  • 举报
回复
其实我在windows上观察过,好像没看到什么额外开销,this指针说到底也就是个地址,在32位的系统上就相当于一个int类型,使用汇编看了windows的情况,简单的push this;就行了,

还有如果在KDevelop中,我想用的G++编译器吧,在类成员函数参数压栈的过程中,cdecl,stdcall和没有使用关键字基本一样,都有一个0xc的开销(非类成员函数没有的),但是fastcall就不是了,我手上也没有什么相关资料,不知道这是什么规范,
archim 2008-10-24
  • 打赏
  • 举报
回复
类成员函数需要this来区分开不同的对象

不然编译器怎么区分这样的调用
a.foo()
b.foo()
coolFly19 2008-10-24
  • 打赏
  • 举报
回复
自己up
coolFly19 2008-10-23
  • 打赏
  • 举报
回复
难道就没有人研究过函数参数压栈弹栈吗?

21,500

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧