Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/132.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于多态调用的x86-64汇编程序 我有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; }_C++_Assembly_X86_X86 64 - Fatal编程技术网

用于多态调用的x86-64汇编程序 我有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; }

用于多态调用的x86-64汇编程序 我有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; },c++,assembly,x86,x86-64,C++,Assembly,X86,X86 64,其中,虚拟呼叫由此asm表示: mov rax,qword ptr [x] mov rax,qword ptr [rax] mov rcx,qword ptr [x] call qword ptr [rax] 这比我预期的vtable方法invocation多了一行。所有四个ASM行是否都特定于多态调用 以上四行如何理解 这是完整的ASM和C++(虚拟调用在结尾是正确的): intmain(){ 添加字节ptr[rax-

其中,虚拟呼叫由此asm表示:

mov         rax,qword ptr [x]  
mov         rax,qword ptr [rax]  
mov         rcx,qword ptr [x]  
call        qword ptr [rax]
这比我预期的vtable方法invocation多了一行。所有四个ASM行是否都特定于多态调用

以上四行如何理解

这是完整的ASM和C++(虚拟调用在结尾是正确的):

intmain(){
添加字节ptr[rax-3333 4h],bh
代表斯托斯·德沃德私人有限公司[rdi]
mov qword ptr[rsp+0A8h],0FFFFFFFFFFFEH
M*x;
o*o=新IO();
mov ecx,70小时
呼叫新接线员(013F6B7A70h)
mov qword ptr[rsp+40h],rax
cmp qword ptr[rsp+40h],0
je干管+4Fh(013F69687Fh)
mov rcx,qword ptr[rsp+40h]
调用IO::IO(013F6814F6h)
mov qword ptr[rsp+0B0h],rax
jmp干管+5Bh(013F69688Bh)
mov qword ptr[rsp+0B0h],0
mov rax,qword ptr[rsp+0B0h]
mov qword ptr[rsp+38小时],rax
mov rax,qword ptr[rsp+38小时]
mov qword ptr[o],rax
H*H=新H(“A”);
mov-ecx,150h
呼叫新接线员(013F6B7A70h)
mov qword ptr[rsp+50小时],rax
cmp qword ptr[rsp+50h],0
je干管+0CEh(013F6968FEh)
lea rax,[rsp+58小时]
mov qword ptr[rsp+80h],rax
lea rdx,[ec_表+11Ch(013F7C073Ch)]
mov rcx,qword ptr[rsp+80h]
调用std::basic_string::basic_string(013F681104h)
mov qword ptr[rsp+0B8h],rax
mov rdx,qword ptr[rsp+0B8h]
mov rcx,qword ptr[rsp+50小时]
呼叫H::H(013F6826A3h)
mov qword ptr[rsp+0C0h],rax
jmp干管+0DAh(013F6990AH)
mov qword ptr[rsp+0C0h],0
mov rax,qword ptr[rsp+0C0h]
mov qword ptr[rsp+48小时],rax
mov rax,qword ptr[rsp+48小时]
mov qword ptr[h],rax
如果(uu rdtsc()%5==0){
rdtsc
shl rdx,20小时
或者rax,rdx
xor edx,edx
mov ecx,5
分区rax,rcx
mov-rax,rdx
测试rax,rax
jne干管+175h(013F6969A5h)
x=新的Y(o,h);
mov-ecx,18h
呼叫新接线员(013F6B7A70h)
mov qword ptr[rsp+90h],rax
cmp qword ptr[rsp+90h],0
je干管+14Ah(013F69697Ah)
mov r8,qword ptr[h]
mov-rdx,qword-ptr[o]
mov rcx,qword ptr[rsp+90小时]
呼叫Y::Y(013F681B4Fh)
mov qword ptr[rsp+0C8h],rax
jmp干管+156h(013F6986h)
mov qword ptr[rsp+0C8h],0
mov rax,qword ptr[rsp+0C8h]
mov qword ptr[rsp+88小时],rax
mov rax,qword ptr[rsp+88小时]
mov qword ptr[x],rax
}
否则{
jmp干管+1DCh(013F696A0Ch)
x=新的Z(o,h);
mov-ecx,18h
呼叫新接线员(013F6B7A70h)
mov qword ptr[rsp+0A0h],rax
cmp qword ptr[rsp+0A0h],0
je干管+1B3h(013F6969E3h)
mov r8,qword ptr[h]
mov-rdx,qword-ptr[o]
mov rcx,qword ptr[rsp+0A0h]
调用Z::Z(013F68160Eh)
mov qword ptr[rsp+0D0h],rax
jmp干管+1BFh(013F69EFH)
mov qword ptr[rsp+0D0h],0
mov rax,qword ptr[rsp+0D0h]
mov qword ptr[rsp+98h],rax
mov rax,qword ptr[rsp+98小时]
mov qword ptr[x],rax
}
x->my_virtual();
mov-rax,qword-ptr[x]
mov-rax,qword-ptr[rax]
mov-rcx,qword-ptr[x]
呼叫qword ptr[rax]
返回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
获取x指向的地址

mov         rax,qword ptr [rax]  
获取x类的vtable地址(使用我们刚刚计算出的rax)。把它放在rax里

mov         rcx,qword ptr [x]  
获取指针x并将其放入rcx中,这样它就可以用作被调用函数中的“this”指针

call        qword ptr [rax]
使用前面找到的vtable中的地址调用函数(没有偏移,因为它是第一个虚拟函数)

如果您打开优化(例如,仅获取[x]一次),编译器可能会使用更短的方法来完成此任务

用伪代码更新Ben Voigt的更多信息:

(*(*m->__vtbl)[0])(m)
优化版本(是否可以使用rcx进行索引?):


第3行更新了
rcx
,而不是
rax
@xxbbcc对不起:)太晚了+1。我想知道
rcx
-我忘了
这个
指针。只是想知道你为什么说它的代码没有优化?多态调用的优化版本是什么?@user997112:例如,我希望优化器能够识别
rax
已经有指向
x
的指针,因此它不需要重新加载它。优化后的序列可能看起来像
mov-rcx,rax;mov-rax[rax],调用qword-ptr[rax]
。但是,如果打开优化器,您可能会得到一些不同的结果,因为导致虚拟调用的内容的codegen可能会发生很大变化,并且寄存器使用选项可能会有所不同(尽管调用约定要求在进行虚拟调用时,
rcx
具有对象指针).@MichaelBurr like Ben Voight在他的答案的第一部分加入了?@user997112:我的想法更像Ben没有第一行的第二个示例,因为优化器会知道
rax
已经包含执行
新操作的一个代码序列中的对象指针。然而,由于优化器也会修改这些序列,因此虚拟调用结束的细节也会改变。所以,谁知道呢,它可能会像本的第一个例子那样结束。第二阶段我不太明白。该命令究竟是如何访问vtable的?@user997112:显然,vtable指针存储在特定布局中的偏移量0处。@TheDark:我认为第二行获取vtabl的地址
call        qword ptr [rax]
(*(*m->__vtbl)[0])(m)
mov         rcx,qword ptr [x]       ; load rcx with object pointer
mov         rax,qword ptr [rcx]     ; load rax with the vtable pointer
call        qword ptr [rax]         ; call through the vtable slot for the virtual function
mov         rax,qword ptr [x]       ; load rax with object pointer
mov         rcx,rax                 ; copy object pointer to rcx (the 'this' pointer)
mov         rax,qword ptr [rax]     ; load rax with the vtable pointer
call        qword ptr [rax]         ; call through the vtable slot for the virtual function