首页
社区
课程
招聘
64位汇编传参问题
发表于: 2020-6-25 13:14 3189

64位汇编传参问题

2020-6-25 13:14
3189

各位大佬好,我在做实验的额时候,书中第四版第四章讲到调用约定时(134-135页)中提到64位下前4个参数传参是:
RCX,RDX,R8,R9
我使用的实验代码(OSX/NASM/GCC)如下:

#include <iostream>
class Demo {
private:
    int x;
    int y;
    int z;
public:
    int a;
    int b;
    int c;
    int getX() { return this->x; }
    int getY() { return this->y; }
    int getZ() { return this->z; }
};

extern "C" Demo* InitMe(Demo*,int,int,int,int,int,int);

int main(int argc, const char * argv[]) {
    Demo* demo = new Demo();
    demo = InitMe(demo,1,2,3,4,5,6);
    std::cout << "X=" << demo->getX() << ",";
    std::cout << "Y=" << demo->getY() << ",";
    std::cout << "Z=" << demo->getZ() << ",";
    std::cout << "A=" << demo->a << ",";
    std::cout << "B=" << demo->b << ",";
    std::cout << "C=" << demo->c << std::endl;
    return 0;
}

InitMe的汇编代码如下:

BITS 64
GLOBAL _InitMe
_InitMe:
    PUSH RBP
    MOV RBP,RSP
    MOV RAX,RDI
    XOR RCX,RCX
    MOV RCX,0x1
    MOV [RAX], RCX
    INC RCX
    MOV [RAX+0x4], RCX
    INC RCX
    MOV [RAX+0x8], RCX
    INC RCX
    MOV [RAX+0xc], RCX
    INC RCX
    MOV [RAX+0x10],RCX
    INC RCX
    MOV [RAX+0x14],RCX
    POP RBP
    RET

通过Ghidra反汇编主函数得到如下反汇编结果:

  this = (void *)__Znwm(0x18);
  _memset(this,0,0x18);
  this = (void *)_InitMe(this,1,2,3,4,5,6);
...
       100000e3d 48 89 45 e0     MOV        qword ptr [RBP + local_28],RAX
       100000e41 e8 86 0f        CALL       __stubs::_memset                                 void * _memset(void * param_1, i
                 00 00
       100000e46 48 8b 45 e0     MOV        RAX,qword ptr [RBP + local_28]
       100000e4a 48 89 45 e8     MOV        qword ptr [RBP + local_20],RAX
       100000e4e 48 8b 7d e8     MOV        RDI,qword ptr [RBP + local_20] ; 这个是Demo*
       100000e52 be 01 00        MOV        ESI,0x1 ; 第一个参数
                 00 00
       100000e57 ba 02 00        MOV        EDX,0x2
                 00 00
       100000e5c b9 03 00        MOV        ECX,0x3
                 00 00
       100000e61 41 b8 04        MOV        R8D,0x4
                 00 00 00
       100000e67 41 b9 05        MOV        R9D,0x5
                 00 00 00
       100000e6d c7 04 24        MOV        dword ptr [RSP]=>local_78,0x6
                 06 00 00 00
       100000e74 e8 80 0e        CALL       _InitMe                                          undefined _InitMe()
                 00 00

编译用命令如下:

# NASM version 2.14.02 compiled on Sep 28 2019
# Apple clang version 11.0.3 (clang-1103.0.32.62)
# Target: x86_64-apple-darwin19.5.0
nasm -fmacho64 InitMe.asm
g++ -v -O0 -ggdb main.cpp InitMe.o

可以看到和书中描述的传参方式不完全一致,特别是Demo*的传递有点特别。我的问题是:这个是编译器的问题呢,还是C++的黑魔法?还是我实验用的代码写得有问题?
谢谢指导!


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (4)
雪    币: 873
活跃值: (531)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
gcc默认是 AMD64 ABI(*nix 上用的), 书上的是 Windows x64 的调用约定,你加上`__attribute__((ms_abi))`就会用微软的了。
或者换成msvc
2020-6-25 16:28
3
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
编译器的问题
2020-6-25 16:31
1
雪    币: 11
活跃值: (89)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
monvvv gcc默认是 AMD64 ABI(*nix 上用的), 书上的是 Windows x64 的调用约定,你加上`__attribute__((ms_abi))`就会用微软的了。 或者换成msvc

明白了,我试了加上__attritebute__((ms_abi)), 现在ghidra看到的反汇编和书上一致了。非常感谢!

       100000e39 48 8b 45 e0     MOV        RAX,qword ptr [RBP + local_28]
       100000e3d 48 89 45 e8     MOV        qword ptr [RBP + local_20],RAX
       100000e41 48 8b 4d e8     MOV        RCX,qword ptr [RBP + local_20]
       100000e45 ba 01 00        MOV        EDX,0x1
                 00 00
       100000e4a 41 b8 02        MOV        R8D,0x2
                 00 00 00
       100000e50 41 b9 03        MOV        R9D,0x3
                 00 00 00
       100000e56 c7 44 24        MOV        dword ptr [RSP + local_88],0x4
                 20 04 00 
                 00 00
       100000e5e c7 44 24        MOV        dword ptr [RSP + local_80],0x5
                 28 05 00 
                 00 00
       100000e66 c7 44 24        MOV        dword ptr [RSP + local_78],0x6
                 30 06 00 
                 00 00
       100000e6e e8 86 0e        CALL       _InitMe                                          undefined _InitMe()
                 00 00
2020-6-25 16:35
0
雪    币: 11
活跃值: (89)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
yy虫子yy 编译器的问题
刚才试了monvvv的回复,证实了是编译器的问题,谢谢虫子的回复。
2020-6-25 16:35
0
游客
登录 | 注册 方可回帖
返回
//