草庐IT

c++ - 用于多态调用的 x86-64 汇编器

coder 2024-02-13 原文

我有 C++ 代码:

int main(){
    M* m;

    O* o = new IO();
    H* h = new H("A");

    if(__rdtsc() % 5 == 0){
        m = new Y(o, h);
    }
    else{
        m = new Z(o, h);
    }

    m->my_virtual();

    return 1;
}

虚拟调用由这个 asm 表示:

mov         rax,qword ptr [x]  
mov         rax,qword ptr [rax]  
mov         rcx,qword ptr [x]  
call        qword ptr [rax]

这比我预期的 vtable 方法调用多了一行。所有四个 ASM 行都特定于多态调用吗?

上面四行怎么伪读?

这是完整的 ASM 和 C++(虚拟调用在最后进行):

int main(){
 add         byte ptr [rax-33333334h],bh  
 rep stos    dword ptr [rdi]  
 mov         qword ptr [rsp+0A8h],0FFFFFFFFFFFFFFFEh  
    M* x;

    o* o = new IO();
 mov         ecx,70h  
 call        operator new (013F6B7A70h) 
 mov         qword ptr [rsp+40h],rax  
 cmp         qword ptr [rsp+40h],0  
 je          main+4Fh (013F69687Fh)  
 mov         rcx,qword ptr [rsp+40h]  
 call        IO::IO (013F6814F6h)  
 mov         qword ptr [rsp+0B0h],rax  
 jmp         main+5Bh (013F69688Bh)  
 mov         qword ptr [rsp+0B0h],0  
 mov         rax,qword ptr [rsp+0B0h]  
 mov         qword ptr [rsp+38h],rax  
 mov         rax,qword ptr [rsp+38h]  
 mov         qword ptr [o],rax  
    H* h = new H("A");
 mov         ecx,150h  
 call        operator new (013F6B7A70h)  
 mov         qword ptr [rsp+50h],rax  
 cmp         qword ptr [rsp+50h],0  
 je          main+0CEh (013F6968FEh)  
 lea         rax,[rsp+58h]  
 mov         qword ptr [rsp+80h],rax  
 lea         rdx,[ec_table+11Ch (013F7C073Ch)]  
 mov         rcx,qword ptr [rsp+80h]  
 call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (013F681104h)  
 mov         qword ptr [rsp+0B8h],rax  
 mov         rdx,qword ptr [rsp+0B8h]  
 mov         rcx,qword ptr [rsp+50h]  
 call        H::H (013F6826A3h)  
 mov         qword ptr [rsp+0C0h],rax  
 jmp         main+0DAh (013F69690Ah)  
 mov         qword ptr [rsp+0C0h],0  
 mov         rax,qword ptr [rsp+0C0h]  
 mov         qword ptr [rsp+48h],rax  
 mov         rax,qword ptr [rsp+48h]  
 mov         qword ptr [h],rax  

    if(__rdtsc() % 5 == 0){
 rdtsc  
 shl         rdx,20h  
 or          rax,rdx  
 xor         edx,edx  
 mov         ecx,5  
 div         rax,rcx  
 mov         rax,rdx  
 test        rax,rax  
 jne         main+175h (013F6969A5h)  
        x = new Y(o, h);
 mov         ecx,18h  
 call        operator new (013F6B7A70h)  
 mov         qword ptr [rsp+90h],rax  
 cmp         qword ptr [rsp+90h],0  
 je          main+14Ah (013F69697Ah)  
 mov         r8,qword ptr [h]  
 mov         rdx,qword ptr [o]  
 mov         rcx,qword ptr [rsp+90h]  
 call        Y::Y (013F681B4Fh)  
 mov         qword ptr [rsp+0C8h],rax  
 jmp         main+156h (013F696986h)  
 mov         qword ptr [rsp+0C8h],0  
 mov         rax,qword ptr [rsp+0C8h]  
 mov         qword ptr [rsp+88h],rax  
 mov         rax,qword ptr [rsp+88h]  
 mov         qword ptr [x],rax  
    }
    else{
 jmp         main+1DCh (013F696A0Ch)  
        x = new Z(o, h);
 mov         ecx,18h  
 call        operator new (013F6B7A70h)  
 mov         qword ptr [rsp+0A0h],rax  
 cmp         qword ptr [rsp+0A0h],0  
 je          main+1B3h (013F6969E3h)  
 mov         r8,qword ptr [h]  
 mov         rdx,qword ptr [o]  
 mov         rcx,qword ptr [rsp+0A0h]  
 call        Z::Z (013F68160Eh)  
 mov         qword ptr [rsp+0D0h],rax  
 jmp         main+1BFh (013F6969EFh)  
 mov         qword ptr [rsp+0D0h],0  
 mov         rax,qword ptr [rsp+0D0h]  
 mov         qword ptr [rsp+98h],rax  
 mov         rax,qword ptr [rsp+98h]  
 mov         qword ptr [x],rax  
    }

    x->my_virtual();
 mov         rax,qword ptr [x]  
 mov         rax,qword ptr [rax]  
 mov         rcx,qword ptr [x]  
 call        qword ptr [rax]  

    return 1;
 mov         eax,1  
}

最佳答案

您可能正在查看未优化的代码:

mov         rax,qword ptr [x]       ; load rax with object pointer
mov         rax,qword ptr [rax]     ; load rax with the vtable pointer
mov         rcx,qword ptr [x]       ; load rcx with the object pointer (the 'this' pointer)
call        qword ptr [rax]         ; call through the vtable slot for the virtual function

关于c++ - 用于多态调用的 x86-64 汇编器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22240460/

有关c++ - 用于多态调用的 x86-64 汇编器的更多相关文章

  1. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  2. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  3. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  6. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  7. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  8. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. ruby - 调用其他方法的 TDD 方法的正确方法 - 2

    我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent

随机推荐