代码如下图
#include<iostream>
using namespace std;
int main() {
const int a{ 1000 };
int* ptrA{ (int*)&a };
*ptrA = 9500;
cout << a << " " << *ptrA << endl;
return 0;
}
按理说是不能改变a的值的,但是我们另辟蹊径,将a的指针用(int*)来强制转换一下,然后操作这个指针变量ptrA,改变ptrA指向的值
结果:
发现a的值并没有发生改变,说明*ptrA和a不是同一个值了
我们分析一下反汇编代码
const int a{ 1000 };
00007FF79681234D mov dword ptr [a],3E8h //立即数寻址,将1000(16进制)的4字节(双字dword)数据移到(ptr指示是a为内存的地址)内存地址为a处(未初始化时候a的值是未知的)
int* ptrA{ (int*)&a };
00007FF796812354 lea rax,[a] //将a的值写入到rax寄存器中,并不是写入a的内存地址,a是1000的内存地址
00007FF796812358 mov qword ptr [ptrA],rax //将rax(a的值)写入到内存地址为ptrA处(八字节)1000的地址
*ptrA = 9500;
00007FF79681235C mov rax,qword ptr [ptrA] //将ptrA指向的八字节内存(1000的地址),移到rax寄存器中
00007FF796812360 mov dword ptr [rax],251Ch //将9500(16进制)移到a指向的位置中
cout << a << " " << *ptrA << endl;
00007FF796812366 mov edx,3E8h //将1000移到了edx中
00007FF79681236B mov rcx,qword ptr [__imp_std::cout (07FF796821190h)]
00007FF796812372 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF796821168h)]
00007FF796812378 lea rdx,[string " " (07FF79681ACA4h)]
00007FF79681237F mov rcx,rax
00007FF796812382 call std::operator<<<std::char_traits<char> > (07FF79681108Ch)
00007FF796812387 mov rcx,qword ptr [ptrA]
00007FF79681238B mov edx,dword ptr [rcx]
00007FF79681238D mov rcx,rax
00007FF796812390 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF796821168h)]
00007FF796812396 lea rdx,[std::endl<char,std::char_traits<char> > (07FF79681103Ch)]
00007FF79681239D mov rcx,rax
00007FF7968123A0 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF796821170h)]
测试代码
#include<iostream>
using namespace std;
int main() {
int a{ 1000 };
cout << &a<<endl;
int* ptrA{ (int*)&a };
*ptrA = 9500;
cout << a << " " << *ptrA << endl;
cout << ptrA<<endl;
cout << &a<<endl;
return 0;
}
结果
发现ptrA和&a指向的地址是一样的,最后输出的结果不一样
查阅了钱林松老师的<c++反汇编与逆向分析技术解密>第62面,解释了#define和const的区别,const修饰的栈常量是伪常量,最终是一个变量,只是在编译期间对语法进行了检查,发现有对const变量存在直接修改行为则报错,所以const修饰的栈常量本质是可以修改的
#include<iostream>
using namespace std;
int main() {
const int a{ 1000 };
cout << &a;
int* ptrA{ (int*)&a };
*ptrA = 9500;
cout << a << " " << *ptrA << endl;
cout << ptrA<<endl;
cout << &a<<endl;
cout << *(&a) << endl;
return 0;
}
主机想试试通过a的地址取出9500,发现是不行的,出现a默认100,因为地址是变动是所以无法通过纯地址访问
其实a那个地址的内存单元已经被修改成了9500,只不过是在编译时候,把a的值的位置都替换成了1000,所以汇编时候那个位置都是1000,在反汇编时候,发现直接是把3E8h直接移到了edx中