代码如下
#include<iostream>
using namespace std;
typedef struct Role {
int HP;
int MP;
}*PRole;
int main() {
Role user;
PRole puser;
puser = &user;
puser->HP = 1500;
puser->MP = 2000;
user.HP = 2500;
user.MP = 3000;
return 0;
}
基础知识
如果是地址就是采用箭头,箭头是偏移的意思,就像x86内核要取出寄存器的信息,定义一个结构体,然后用偏移来访问各个寄存器的值
实体取出值就是按点(.)来访问
反汇编代码
发现在定义结构体的部分是没有汇编代码的
原因:只有在定义这个结构体变量时候,编译器就去看这个结构体的定义,然后结构体都是基础数据类型组成的,占用内存的大小都是确定的,所以可以通过偏移来访问结构体的成员
Role user;
PRole puser;
puser = &user;
00007FF6EC26185D lea rax,[user] //将user的地址放到rax中
00007FF6EC261861 mov qword ptr [puser],rax //将user的地址给puser地址指向的内存
可能是现在vscode编辑器的优化,把一些压栈的操作给忽略了,所以更加直白一些
puser->HP = 1500;
00007FF6EC261865 mov rax,qword ptr [puser] //将user地址给到rax,puser是通过栈拿的
00007FF6EC261869 mov dword ptr [rax],5DCh //给结构体第一个元素赋值,就像数组一样数组名是第一个元素的地址
puser->MP = 2000;
00007FF6EC26186F mov rax,qword ptr [puser] //和上面同理
00007FF6EC261873 mov dword ptr [rax+4],7D0h //给结构体第二个元素赋值,偏移4个字节,内存中偏移
user.HP = 2500;
00007FF6EC26187A mov dword ptr [user],9C4h //给结构体第一个元素赋值
user.MP = 3000;
00007FF6EC261881 mov dword ptr [rbp+0Ch],0BB8h //给结构体第二个元素赋值,栈偏移,通过栈来拿这个局部变量
还有一种情况
PRole puser = new Role
,这是将在堆中创建了两个int变量,然后puser指向第一个int变量
Role user;
PRole puser;
puser = new Role;
00007FF7B032198C mov ecx,8
00007FF7B0321991 call operator new (07FF7B032103Ch)
00007FF7B0321996 mov qword ptr [rbp+108h],rax
00007FF7B032199D mov rax,qword ptr [rbp+108h]
00007FF7B03219A4 mov qword ptr [puser],rax
user.HP = 2500;
00007FF7B03219A8 mov dword ptr [user],9C4h
user.MP = 3000;
00007FF7B03219AF mov dword ptr [rbp+0Ch],0BB8h