I have the C++ code:
我有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;
}
where the virtual call is represented by this asm:
其中虚拟调用由asm表示:
mov rax,qword ptr [x]
mov rax,qword ptr [rax]
mov rcx,qword ptr [x]
call qword ptr [rax]
It is one more line than I was expecting for the vtable method invoccation. Are all four of the ASM lines specific to the polymorphic call?
这比我预期的vtable方法调用多了一行。ASM中所有的四条线都是针对多态调用的吗?
How do the above four lines read pseudo-ly?
以上四行如何读伪ly?
This is the complete ASM and C++ (the virtual call is made right at the end):
这是完整的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
}
3 个解决方案
#1
6
You're probably looking at unoptimized code:
您可能会看到未优化的代码:
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
#2
4
mov rax,qword ptr [x]
get the address pointed to by x
得到x指向的地址
mov rax,qword ptr [rax]
get the address of the vtable for x's class (using rax we just worked out). Put it in rax
获取x类的vtable的地址(使用我们刚刚计算出来的rax)。把它放在伸展
mov rcx,qword ptr [x]
get the pointer x and put it in rcx, so it can be used as the "this" pointer in the called function.
获取指针x并将其放入rcx中,以便在调用函数中将其用作“this”指针。
call qword ptr [rax]
call the function using the address from the vtable we found earlier (no offset as it is the first virtual function).
使用前面找到的vtable中的地址调用函数(没有偏移量,因为它是第一个虚函数)。
There are definitely shorter ways to do it, which the compiler might use if you switch optimizations on (e.g. only get [x] once).
肯定有更短的方法,如果您打开优化(例如,只有一次get [x]),编译器可能会使用这种方法。
Updated with more info from Ben Voigt
Ben Voigt更新了更多信息
#3
2
In pseudo-code:
在伪代码:
(*(*m->__vtbl)[0])(m)
Optimized version (can rcx
be used for indexing?):
优化版本(rcx是否可用于索引?):
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
or
或
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
#1
6
You're probably looking at unoptimized code:
您可能会看到未优化的代码:
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
#2
4
mov rax,qword ptr [x]
get the address pointed to by x
得到x指向的地址
mov rax,qword ptr [rax]
get the address of the vtable for x's class (using rax we just worked out). Put it in rax
获取x类的vtable的地址(使用我们刚刚计算出来的rax)。把它放在伸展
mov rcx,qword ptr [x]
get the pointer x and put it in rcx, so it can be used as the "this" pointer in the called function.
获取指针x并将其放入rcx中,以便在调用函数中将其用作“this”指针。
call qword ptr [rax]
call the function using the address from the vtable we found earlier (no offset as it is the first virtual function).
使用前面找到的vtable中的地址调用函数(没有偏移量,因为它是第一个虚函数)。
There are definitely shorter ways to do it, which the compiler might use if you switch optimizations on (e.g. only get [x] once).
肯定有更短的方法,如果您打开优化(例如,只有一次get [x]),编译器可能会使用这种方法。
Updated with more info from Ben Voigt
Ben Voigt更新了更多信息
#3
2
In pseudo-code:
在伪代码:
(*(*m->__vtbl)[0])(m)
Optimized version (can rcx
be used for indexing?):
优化版本(rcx是否可用于索引?):
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
or
或
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