汇编和 c/c++ 指针
最编程
2024-03-02 07:07:43
...
直接上代码,注意区分变量和指针变量,其实它们两个是不同的类型,指针变量存储的值永远都是4字节类型(内存地址)。 c++代码 `int i,*p; { _asm { mov eax,eax mov eax,eax }
//区分下面的指针变量和变量
//00401005 8B35 A4204000 MOV ESI,DWORD PTR DS:[<&MSVCR100.printf>>; 将打印函数存储到esi,可能是优化原因
//00401015 C705 6C334000 3>MOV DWORD PTR DS:[i],0x8235 ; 赋值操作
i = 33333;
//0040101F C705 70334000 6>MOV DWORD PTR DS:[p],OFFSET test_poi.i ; UNICODE "舵"
p = &i;//i地址赋值给p
//0040100B 68 6C334000 PUSH OFFSET test_poi.i ; 直接取i地址
//00401010 68 F4204000 PUSH test_poi.004020F4 ; ASCII "i变量地址是:0x%x\n"
//CALL ESI
printf("i变量地址是:0x%x\n",&i);//i的地址
//0040102B A1 6C334000 MOV EAX,DWORD PTR DS:[i] ; i取值,,赋值到eax
//00401030 50 PUSH EAX
//00401031 68 08214000 PUSH test_poi.00402108 ; ASCII "i变量数值是:%d\n"
//00401036 FFD6 CALL ESI ; msvcr100.printf
printf("i变量数值是:%d\n",i);//i值
//printf("i变量数值是:%\n",*i);//错误的,因为不是指针类型所以不可以通过编译,只有强制转换才可以
//printf("i变量数值是:%\n",*((int*)i));//可以运行,但是会抛出异常。除非i是一个有效的地址,否则异常
//00401038 8B0D 70334000 MOV ECX,DWORD PTR DS:[p] ; 取p的值,这个ecx是取值寄存器,下同
//0040103E 51 PUSH ECX ; msvcr100.78B05617
//0040103F 68 1C214000 PUSH test_poi.0040211C ; ASCII "*p变量地址是:0x%x\n"
//00401044 FFD6 CALL ESI ; msvcr100.printf
//最难理解,放在最后看
printf("*p变量地址是:0x%x\n",*&p);//*&p和&*p相同, 等同于p指针变量的值,1.&*p,先取出i的值(最后一步),然后&i。2.*&p,先得到指针变量p的地址,然后在取地址,然后继续获取指针p的地址,假定一个临时指针变量temp的值是此地址,在取得执行*temp,先取出指针变量temp的值,在用temp的值当做地址来取值(这个才是星号的作用)
//00401046 68 70334000 PUSH OFFSET test_poi.p ; 取指针变量p的地址
//0040104B 68 30214000 PUSH test_poi.00402130 ; ASCII "p变量地址是:0x%x\n"
//00401050 FFD6 CALL ESI ; msvcr100.printf
printf("p变量地址是:0x%x\n",&p);//指针变量p的地址
//00401052 8B15 70334000 MOV EDX,DWORD PTR DS:[p] ; 取指针变量p的值,值为i的地址
//00401058 52 PUSH EDX ; msvcr100.78B55550
//00401059 68 44214000 PUSH test_poi.00402144 ; ASCII "p变量数值是:%x\n"
//0040105E FFD6 CALL ESI ; msvcr100.printf
printf("p变量数值是:%x\n",p);//获取指针变量p的值
//00401060 A1 70334000 MOV EAX,DWORD PTR DS:[p] ; 取指针p的值,值为i的地址
//00401065 8B08 MOV ECX,DWORD PTR DS:[EAX] ; 取eax的值,即i地址的值
//00401067 51 PUSH ECX ; msvcr100.78B05617
//00401068 68 58214000 PUSH test_poi.00402158 ; ASCII "p变量数指向值是:%d\n"
//0040106D FFD6 CALL ESI ; msvcr100.printf
printf("p变量数指向值是:%d\n",*p);//分成两部,先取出指针变量p的值,在用p的值当做地址来取值(这个才是星号的作用)
/*i变量地址是:0x40336c
i变量数值是:33333
*p变量地址是:0x40336c
p变量地址是:0x403370
p变量数值是:40336c
p变量数指向值是:33333*/
getchar();
return 0;
}
汇编代码
00401000 > $ 56 PUSH ESI
00401001 . 8BC0 MOV EAX,EAX ; 花指令
00401003 . 8BC0 MOV EAX,EAX ; 花指令
00401005 . 8B35 A4204000 MOV ESI,DWORD PTR DS:[<&MSVCR100.printf>>; 将打印函数存储到esi,可能是优化原因
0040100B . 68 6C334000 PUSH OFFSET test_poi.i ; /直接放入i地址
00401010 . 68 F4204000 PUSH test_poi.004020F4 ; |format = "i变量地址是:0x%x
"
00401015 . C705 6C334000>MOV DWORD PTR DS:[i],0x8235 ; |赋值操作
0040101F . C705 70334000>MOV DWORD PTR DS:[p],OFFSET test_poi.i ; |
00401029 . FFD6 CALL ESI ; \调用函数esi地址,即printf
0040102B . A1 6C334000 MOV EAX,DWORD PTR DS:[i] ; 通过ds寻址取值,,赋值到eax
00401030 . 50 PUSH EAX
00401031 . 68 08214000 PUSH test_poi.00402108 ; ASCII "i变量数值是:%d\n"
00401036 . FFD6 CALL ESI
00401038 . 8B0D 6C334000 MOV ECX,DWORD PTR DS:[i] ; 取p的值,这个ecx是取值寄存器
0040103E . 8B11 MOV EDX,DWORD PTR DS:[ECX]
00401040 . 52 PUSH EDX
00401041 . 68 1C214000 PUSH test_poi.0040211C ; ASCII "i变量数值是:%\n"
00401046 . FFD6 CALL ESI ; 取变量p的值
00401048 . A1 70334000 MOV EAX,DWORD PTR DS:[p]
0040104D . 50 PUSH EAX
0040104E . 68 2C214000 PUSH test_poi.0040212C ; ASCII "*p变量地址是:0x%x\n"
00401053 . FFD6 CALL ESI
00401055 . 68 70334000 PUSH OFFSET test_poi.p
0040105A . 68 40214000 PUSH test_poi.00402140 ; ASCII "p变量地址是:0x%x\n"
0040105F . FFD6 CALL ESI
00401061 . 8B0D 70334000 MOV ECX,DWORD PTR DS:[p]
00401067 . 51 PUSH ECX ; msvcr100.__winitenv
00401068 . 68 54214000 PUSH test_poi.00402154 ; ASCII "p变量数值是:%x\n"
0040106D . FFD6 CALL ESI
0040106F . 8B15 70334000 MOV EDX,DWORD PTR DS:[p]
00401075 . 8B02 MOV EAX,DWORD PTR DS:[EDX]
00401077 . 50 PUSH EAX
`
推荐阅读
-
C++] -- c++11 智能指针
-
深入了解 C++ lambda 表达式:用法、特性和最佳实践
-
贪婪算法在 Python、JavaScript、Java、C++ 和 C# 中的多种实现及其在硬币变化、分数骑士、活动选择和使用哈夫曼编码的最小生成树问题中的应用实例
-
MySql C++ 调用库 连接器/c++ 编译和接口包 [I] mysql 数据库安装
-
C++ 入门语法(命名空间、默认函数、函数重载、引用、内联函数和 nullptr)
-
C++ 静态和动态绑定
-
保留有效数字和小数位的 C++ 浮点运算
-
c++ 保留重要位数和小数位数 -II.
-
C++ 保留有效位数和小数位数。
-
C++ 保留有效数字和小数位数