指针示例
学习了计算机组成原理之后,对指针有了新的认识
首先是计算机存储结构
当程序运行时,我们关注寄存器和主存
写一段指针的代码
1 2 3 4 5 6 7
| int main() { int y = 0; int *p=&y; *p = 1; return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10
| int y = 0; 010216A8 mov dword ptr [y],0 int *p=&y; 010216AF lea eax,[y] 010216B2 mov dword ptr [p],eax *p = 1; 010216B5 mov eax,dword ptr [p] 010216B8 mov dword ptr [eax],1 return 0; 010216BE xor eax,eax
|
我的汇编代码格式是Intel的,dword ptr [p]表示一个内存的位置
在指令中,如果指明了某个专用寄存器,也就指明了要处理的数据的尺寸
在没有寄存器名存在的情况下,用操作符 X ptr 指明内存单元的长度,X可以是word或byte ;
有些指令默认了访问的是字单元还是字节单元,比如:push [1000H] 就不用指明访问的是字单元还是字节单元,因为push指令只进行字操作。
Intel的字(word)表示16位数据;一字节八位;b,w,l,q对应1,2,4,8字节
1 2 3 4 5
| int y = 0; 010216A8 mov dword ptr [y],0 int *p=&y; 010216AF lea eax,[y] 010216B2 mov dword ptr [p],eax
|
所以让指针p指向y实际是三条指令
把立即数0传到内存y中,给y赋值 int y = 0;
取内存y的有效地址,传到寄存器eax中 &y;
把寄存器eax的值,传到内存y中 赋值
c和指针中说,等号左边是地址,右边是一个值,指针存放的是指向的地址
在汇编中,就有了更直观的体现
比如c语言的值传递和地址传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include "stdafx.h" #include <stdio.h> void swap0(int a0, int b0) { int tmp0 = b0; b0 = a0; a0 = tmp0; } void swap1(int *a1, int *b1) { int tmp1 = *b1; *b1 = *a1; *a1 = tmp1; }
int main() { int x0 = 1,y0 = 2; int x1 = 2, y1 = 2; swap0(x0, y0); swap1(&x1, &y1); return 0; }
|
反汇编
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| int x0 = 0,x1 = 1; 00C44568 mov dword ptr [x0],0 00C4456F mov dword ptr [x1],1 int y0 = 0, y1 = 1; 00C44576 mov dword ptr [y0],0 00C4457D mov dword ptr [y1],1 swap0(x0, x1); 00C44584 mov eax,dword ptr [x1] 00C44587 push eax 00C44588 mov ecx,dword ptr [x0] 00C4458B push ecx 00C4458C call swap0 (0C41343h) 00C44591 add esp,8 swap1(&y0, &y1); 00C44594 lea eax,[y1] 00C44597 push eax 00C44598 lea ecx,[y0] 00C4459B push ecx 00C4459C call swap1 (0C41348h) 00C445A1 add esp,8 return 0; 00C445A4 xor eax,eax
|
对比下两边的操作
swap0(值传递) |
swap1(地址传递) |
mov eax,dword ptr [x1] |
lea eax,[y1] |
拷贝了一份值传到寄存器eax |
取了y1的地址到eax |
swap0
1 2 3 4 5 6 7 8 9
| int tmp0 = b0; 00C4169E mov eax,dword ptr [b0] 00C416A1 mov dword ptr [tmp0],eax b0 = a0; 00C416A4 mov eax,dword ptr [a0] 00C416A7 mov dword ptr [b0],eax a0 = tmp0; 00C416AA mov eax,dword ptr [tmp0] 00C416AD mov dword ptr [a0],eax
|
swap1
1 2 3 4 5 6 7 8 9 10 11 12 13
| int tmp1 = *b1; 00C416DE mov eax,dword ptr [b1] 00C416E1 mov ecx,dword ptr [eax] 00C416E3 mov dword ptr [tmp1],ecx *b1 = *a1; 00C416E6 mov eax,dword ptr [b1] 00C416E9 mov ecx,dword ptr [a1] 00C416EC mov edx,dword ptr [ecx] 00C416EE mov dword ptr [eax],edx *a1 = tmp1; 00C416F0 mov eax,dword ptr [a1] 00C416F3 mov ecx,dword ptr [tmp1] 00C416F6 mov dword ptr [eax],ecx
|
两边的函数确实都交换了,不同
swap0 |
swap1 |
交换拷贝的值 |
按地址寻址,交换的实际是内存中的值 |