我明白我表达不够清晰。我的疑惑,我认为,可以总结为:
在一个可执行文件(机器码)中,“变量”是如何表示的?它们是静态内存地址吗?编译器会给每个变量分配一个特定的“名称”(还是只保留您给它们的名称)?
用代码来表达:
int x=5;
//Bunch of code
cin>>y;
cout<<x+1;
每台计算机中的程序如何知道哪个地址将持有值5,以保存输入的值、将1添加到它现在持有的值并最终打印相同的值。
-- João
我明白我表达不够清晰。我的疑惑,我认为,可以总结为:
在一个可执行文件(机器码)中,“变量”是如何表示的?它们是静态内存地址吗?编译器会给每个变量分配一个特定的“名称”(还是只保留您给它们的名称)?
用代码来表达:
int x=5;
//Bunch of code
cin>>y;
cout<<x+1;
每台计算机中的程序如何知道哪个地址将持有值5,以保存输入的值、将1添加到它现在持有的值并最终打印相同的值。
-- João
这是与实现相关的。
通常,变量的位置将基于各种因素和优化。它们可能根本不会存在于RAM中,因为它们可能被优化以完全存在于寄存器中,或者被完全优化掉。
变量名在运行时不存在;它们在编译期间被丢弃。但是,编译器可以发出存储在应用程序二进制文件中的调试信息,以允许开发人员调试应用程序。尽管如此,这通常会在发布版本中删除。
我对Gameshark的具体情况一无所知。但在许多情况下,通过查看应用程序的机器代码可以找到特定变量的位置。
这是一个简单的C语言程序:
int main() {
int a = 5;
int b = 7;
int c = a + b;
return 0;
}
gcc -m32 -S -O0 -o main.s main.c
进行编译,您将得到类似于以下内容的结果。 .file "main.c"
.text
.globl main
.type main, @function
main:
.LFB0:
/* %ebp is a Base Pointer Register */
pushl %ebp
movl %esp, %ebp
/* Here we reserve space for our variables */
subl $16, %esp
/* a's address is %ebp - 4 */
movl $5, -4(%ebp)
/* b's address is %ebp - 8 */
movl $7, -8(%ebp)
/* a + b */
movl -8(%ebp), %eax
movl -4(%ebp), %edx
addl %edx, %eax
/* c's address is %ebp - 12 */
movl %eax, -12(%ebp)
/* return 0 */
movl $0, %eax
leave
ret
如您所见,在这种情况下,变量地址是作为函数基指针的偏移量来计算的。如果启用优化,变量的值可能会存储在寄存器中。
所以这有两个部分,我会尽力而为。
在编译时,编译器将把C++代码转换为内部表示形式。然后,它会尽可能高效地使用CPU寄存器,并将其余数据推入RAM中。随着程序的执行,来自RAM的数据将被复制到寄存器中来回传递。
关于您的另一个问题,我见过人们用的一种方法是针对用户拥有的黄金。程序可以获取整个游戏的内存空间并进行复制。然后,用户执行某些操作(最小操作)以获得或失去黄金。外部应用程序随后搜索整个内存空间以查找哪些值已更改,以及先前的黄金数量和当前的黄金数量。一旦他们找到此位置,他们就能够编辑内存位置并将其更新为任何他们想要的值。
通常情况下,游戏越复杂,该方法就越困难。