关于大会和计算机程序的问题

时间:2011-08-14 13:46:23

标签: assembly linker executable

我读过这篇文章:http://en.wikipedia.org/wiki/Assembly_language

它说:

  

例如,告诉x86 / IA-32处理器的指令   将一个8位立即值移入寄存器。二进制代码   该指令是10110,后跟一个3位标识符   注册使用。 AL寄存器的标识符是000,所以   以下机器代码将AL寄存器加载到数据中   01100001. [4]

     

10110000 01100001

它解释了如何更容易地将其编写为:

MOV AL, 61h       ; Load AL with 97 decimal (61 hex)

现在这是我的问题。

那么,计算机程序/可执行文件只是二进制数据(0' s和1' s)?

当使用像OllyDbg这样的反汇编程序查看时,它只是试图将那些0和1还原为某种汇编(英特尔?)语言并且输出大部分是正确的?

如果我在我的SSD上有这个10110000 01100001程序,并且我编写了一个C#/ PHP / wtvr应用程序,它读取文件的内容并将其作为位输出,我是否会看到这些10110000 01100001个数字?

操作系统如何执行实际"执行"?它如何告诉处理器"嘿,拿这些位并运行它们"?我可以直接在C#/ C ++中这样做吗?

3 个答案:

答案 0 :(得分:2)

  

那么,计算机程序/可执行文件只是二进制数据(0和1)?

是的,如图片,视频和其他数据。

  

当使用像OllyDbg这样的反汇编程序查看时,它只是试图将那些0和1重新恢复为某种汇编(英特尔?)语言,输出大多是正确的?

是的,在这种情况下,它始终是正确的,因为mov al, 61h始终汇总到0xB0 0x61(在Intel 64 and IA-32 Architectures Software Developer's Manuals和其他地方通常写为B0 61)16 - ,32位和64位模式。请注意0xB0 0x61 = 0b10110000 0b01100001

您可以在第2A卷中找到不同指令的编码。例如,这里是“B0 + rb MOV r8,imm8 E有效有效移动imm8到r8”。第3-644页。

其他指令具有不同的含义取决于它们是以16/32还是64位模式解释。考虑这个短的字节序列:66 83 C0 04 41 80 C0 05

在16位模式下,它们意味着:

00000000  6683C004          add eax,byte +0x4
00000004  41                inc cx
00000005  80C005            add al,0x5

在32位模式下,它们意味着:

00000000  6683C004          add ax,byte +0x4
00000004  41                inc ecx
00000005  80C005            add al,0x5

最后是64位模式:

00000000  6683C004          add ax,byte +0x4
00000004  4180C005          add r8b,0x5

因此,在不知道上下文的情况下,不能总是正确地反汇编指令(这甚至没有考虑除了代码之外的其他东西可以驻留在文本段中,并且代码可以做一些令人讨厌的事情,比如生成代码或者自动生成代码修改)。

  

如果我在我的SSD上有这个10110000 01100001程序,并且我编写了一个C#/ PHP / wtvr应用程序,它读取文件的内容并将它们输出为位,我会看到这些10110000 01100001数字吗?

是的,从某种意义上说,如果应用程序包含mov al, 61h指令,则该文件将包含字节0xB00x61

  

操作系统如何执行实际的“执行”?它如何告诉处理器“嘿,拿这些位并运行它们”?我可以直接在C#/ C ++中这样做吗?

将代码加载到内存中(并且允许正确设置内存)后,它可以跳转或调用它并使其运行。有一点你必须要意识到,即使操作系统只是另一个程序,它是一个特殊的程序,因为它首先到达处理器!它以特殊的管理程序(或管理程序)模式运行,允许它不允许正常(用户)程序。就像设置preemptive multitasking一样,可以确保自动生成进程。

第一个处理器还负责唤醒多核/多处理器机器上的其他核心/处理器。请参阅this SO问题。

要调用直接在C ++中加载自己的代码(我认为在C#中不可能使用不安全/本机代码),需要特定于平台的技巧。对于Windows,您可能希望查看VirtualProtect和linux mprotect(2)下的内容。或者更真实地来自使用this process for Windowsmmap(2)为linux映射的文件。

答案 1 :(得分:1)

这是很多问题:

是的,计算机程序/可执行文件只是二进制数据0/1。

是的,反汇编程序尝试理解0/1 ...并且它使用了关于文件格式的额外知识(EXE通常遵循PE规范,COM是不同规范等)和二进制文件应该使用的操作系统运行和API可用等。

这两个字节(带参数的一条指令)读起来就像那样......虽然它取决于它们所属的程序 - 如上所述,不同的文件类型遵循不同的规范。

通常,操作系统会根据规范加载文件并处理其内容 - 例如重新排列某些内存区域等。然后它将包含可执行代码的内存区域标记为可执行文件,并对所谓入口点的第一条指令的地址执行JMP或CALL(同样,这取决于手头的文件格式/规范)。

在C#中你不会将程序集作为一种语言处理,而是使用“字节代码”(IL指令)...你可以通过Framework方法等发出thos或加载thos等。 在c ++中你可以直接处理程序集,如果你真的想要,但那不可移植并且可能变得复杂......所以你通常只在获得真正值得的时候这样做(比如需要的性能提升10倍)。 / p>

答案 2 :(得分:1)

  

那么,计算机程序/可执行文件只是二进制数据(0和1)?

YES。

  

当像OllyDbg这样的反汇编程序查看时,它只是试图恢复   那些0和1回到了一些大会(英特尔?)语言和   输出大多是正确的吗?

YES。除非二进制数据代表反汇编程序设计的cpu代码,否则输出将完全正确,而不仅仅是“大部分”正确。

  

如果我在我的SSD上有这个10110000 01100001程序而且我写了一个   C#/ PHP / wtvr应用程序,用于读取文件和输出的内容   它们作为位,我会看到这些确切的10110000 01100001数字吗?

YES

  

操作系统如何执行实际的“执行”?怎么做的   告诉处理器“嘿,拿这些位并运行它们”?

操作系统只是一个与其他程序一样的程序,它是在处理器上执行的指令。简单地说,当操作系统执行代码时,它只是跳转到代码所在位置的起始地址,因此处理器现在开始执行该位置的任何代码。

  

我可以直接在C#/ C ++中这样做吗?

不要忘记C在执行时被编译成汇编语言,并且在执行它时,它与可以在给定CPU上运行的任何其他程序没有什么不同。是的,您可以使用内联汇编来跳转到给定的内存位置并执行代码。