这让我感到困惑的原因是所有地址都包含1和0的序列。那么CPU如何区分,让我们说00000100
(整数)来自00000100
(CPU指令)?
答案 0 :(得分:5)
首先,不同的命令具有不同的值(操作码)。那就是CPU如何知道要做什么。
最后,问题仍然存在:什么是命令,什么数据?
现代PC正在使用 von Neumann - 架构(https://en.wikipedia.org/wiki/John_von_Neumann),其中数据和操作码存储在同一个内存空间中。 (这两种数据类型之间存在分离的架构,例如哈佛架构)
详细解释所有内容将完全超出stackoverflow的范围,很可能每个帖子的字符数量不足以满足要求。
用尽可能少的单词来回答这个问题(在这个级别上实际工作的每个人都会因为解释中的捷径而杀了我):
因此,假设应该执行添加,并且内存中有3个地址可用,应用程序将存储(在5+7
的情况下)(我使用"动词"用于说明)
Adress | Stored Value
1 | ADD
2 | 5
3 | 7
最后CPU收到指令1 2 3
,这意味着ADD 5 7
(这些东西对命令敏感![命令] [v1] [v2])......现在事情变得复杂了
CPU会将这些值(实际上不是值,只是值的地址)移动到寄存器中,然后对其进行处理。要选择的确切寄存器取决于数据类型,数据大小和操作码。
对于命令#1 #2 #3
,CPU将首先读取这些内存地址,然后知道需要ADD 5 7
。
根据ADD
的操作码,CPU会知道:
#2
放入r1 #3
放入r2 注意这是简化的。实际上,CPU需要有关处理值或地址的确切指令。在汇编中,这是通过使用
完成的CPU无法对存储在存储器中的值执行计算,因此将值从存储器移动到寄存器以及从寄存器移动到存储器非常繁忙。
即。如果你有
eax = 0x2
并且在记忆中
0x2 = 110011
和指令
MOV ebx, [eax]
这意味着:将当前存储在地址中的值(当前存储在eax
中)移动到寄存器ebx
中。最后
ebx = 110011
(每次CPU发生一次计算都会发生这种情况!内存 - >注册 - >内存)
最后,要求苛刻的应用程序可以读取其预定义的内存地址#2,
得到地址#2568,然后知道计算结果存储在地址#2568。读取该地址将导致值12
(5 + 7)
这只是一个很小的例子。有关此问题的更详细介绍,请参阅http://www.cs.virginia.edu/~evans/cs216/guides/x86.html
人们无法真正掌握为简单添加2个值所做的数据移动量和计算量。做一些CPU(纸上)会花几分钟来计算" 5 + 7",因为没有" 5"没有" 7" - 一切都隐藏在内存中的一个地址后面,指向一些位,导致不同的值取决于地址0x1的位指示...
答案 1 :(得分:3)
简短形式:CPU不知道那里存储了什么,但是指令告诉CPU如何解释它。
我们有一个简化的例子。
如果CPU被告知要添加一个存储在X位置的字(比方说,32位整数),它会获取该地址的内容并添加它。
如果程序计数器到达同一位置,CPU将再次获取该字并将其作为命令执行。
答案 2 :(得分:1)
CPU(NX位之类的安全产品除外)对其数据或代码是盲目的。
数据不会被意外地作为代码执行的唯一方法是通过仔细地组织代码,从不引用保存数据的位置以及用于操作代码的指令。
当程序启动时,处理器开始在预定义的位置执行它。用机器语言编写的程序的作者将故意将程序的开头放在那里。从那里,该指令将始终最终设置处理器将执行的下一个位置,这是一个指令。除非代码中存在严重错误,否则构成程序的所有指令的情况仍然如此。
指令可以设置处理器下一步的两种主要方式:跳转/分支,而不是明确指定。如果指令没有明确指定下一步,则CPU默认为当前指令之后的位置。对比跳转和分支,它们具有专门编码下一条指令地址的地址的空间。跳转始终跳转到指定的位置。分支检查条件是否为真。如果是,CPU将跳转到编码位置。如果条件为假,它将直接转到分支后的指令。
此外,机器语言程序不应该将数据写入用于指令的位置,或者程序中某些其他指令可能会尝试运行被数据覆盖的内容。发生这种情况可能会导致各种不良事件发生。那里的数据可能有一个"操作码"这与处理器不知道该怎么做的任何东西都不匹配。或者,那里的数据可以告诉计算机做一些完全无意的事情。无论哪种方式,你都会度过糟糕的一天。很高兴你的编译器永远不会搞砸,并且不小心插入了这样做的东西。
不幸的是,有时使用编译器的程序员会搞砸,并做一些事情,告诉CPU在他们为数据分配的区域之外写入数据。 (在C / C ++中,这种情况的一种常见方式是分配一个L项长的数组,并在写入数据时使用索引> = L.)将数据写入为代码留出的区域是缓冲区溢出漏洞的组成部分。某些程序可能存在一个错误,该错误允许远程计算机欺骗程序将数据(远程机器发送的数据)写入超出为数据预留的区域的末尾,并进入为代码留出的区域。然后,在稍后的某个时刻,处理器执行"数据" (记住,这是从远程计算机发送的)。如果远程计算机/攻击者很聪明,他们会精心制作数据"超越边界是有效的指令做恶意的事情。 (为了给他们更多的访问权限,销毁数据,从内存中发回敏感数据等)。
答案 3 :(得分:0)
这是因为ISA必须考虑一组有效的指令以及如何编码数据:内存地址/寄存器/文字。
有关如何设计ISA的更多常规信息,请参阅此处 https://en.wikipedia.org/wiki/Instruction_set
答案 4 :(得分:0)
简而言之,操作系统会告诉它下一条指令的位置。在x64的情况下,有一个称为rip(指令指针)的特殊寄存器,它保存下一条要执行的指令的地址。它将自动读取该地址的数据,解码并执行它,并自动将rip增加指令的字节数。
通常,OS可以将存储器(页面)的区域标记为保留可执行代码。如果错误或漏洞尝试修改可执行内存,则应该发生错误,类似地,如果CPU发现自己试图执行非可执行内存,它将/应该发出错误并终止程序。现在,您将进入软件病毒的精彩世界!