Assembly x86汇编在哪个CPU上工作?

Assembly x86汇编在哪个CPU上工作?,assembly,x86,nasm,x86-64,masm,Assembly,X86,Nasm,X86 64,Masm,我花了几年时间用C和Java编写代码。我喜欢让一个程序显示一个消息框或执行一些文件操作,它可以在每个(我想?)CPU上工作,而不需要任何戏剧。尽管我从未编写过任何高级代码 我想学习汇编,仅适用于Windows。我认为我应该学习一种叫做x86 asm的东西 我的问题:如果我不想做一些太疯狂或晦涩的事情,我创建的程序会在每个CPU上工作吗?我的重点是你家里的普通电脑或者服务器 我有很多人告诉我,我必须从许多著名的来源中为特定的CPU选择特定的体系结构,但随后我看到了在几个不同的CPU上工作的代码示例

我花了几年时间用C和Java编写代码。我喜欢让一个程序显示一个消息框或执行一些文件操作,它可以在每个(我想?)CPU上工作,而不需要任何戏剧。尽管我从未编写过任何高级代码

我想学习汇编,仅适用于Windows。我认为我应该学习一种叫做x86 asm的东西

我的问题:如果我不想做一些太疯狂或晦涩的事情,我创建的程序会在每个CPU上工作吗?我的重点是你家里的普通电脑或者服务器

我有很多人告诉我,我必须从许多著名的来源中为特定的CPU选择特定的体系结构,但随后我看到了在几个不同的CPU上工作的代码示例。。。冲突信息

编辑: 我只想写一些程序,在汇编中寻找乐趣,而不必担心我的朋友约翰·多伊在他的计算机上使用它时会有麻烦。我可以很容易地用C编写一个程序,它可以显示一条消息、ping google.com和其他任何东西,而不必担心CPU。asm真的不一样吗?o、 o

EDIT2: 也许我感到困惑,因为我不知道在Windows上用C编写的普通(没什么特别的)程序在哪个CPU上工作。。。只有英特尔和AMD?

不能在CPU上工作。它需要被称为汇编程序的程序转换为。这种转换通常很简单(通常,汇编程序将包含汇编代码的文本转换为某些目标代码;链接器然后将多个目标文件聚合为一个可执行文件,并解析重定位;该可执行文件包含机器代码)

有几个汇编程序语法(例如vs)

x86有几种变体(例如,一些处理器,但不是全部,接受扩展,如32位对64位)


最后,针对Windows的user land x86程序在运行其他操作系统(例如Linux)的同一x86体系结构(甚至同一硬件)上不起作用,因为可执行文件格式(在Windows上,在Linux上)不同。阅读更多有关操作系统的信息。

让我们一步一步来:

  • asm代码是相同的如果处理器是相同的,那么操作系统并不重要,因此您不必关注Windows
  • 是的,您必须选择特定的体系结构(或者您应该选择)。每个体系结构都有不同的指令集。进一步的说明,为了设计一个合适的程序,您必须了解体系结构(寄存器、地址、总线…),所以这绝对不是小事
  • asm并不容易,实际上非常困难,因此如果目标是复杂的任务(服务器?),那么困难就几乎不可能实现。如果这是一个问题(或架构),您可以尝试更高的级别,例如C
  • 可以在不同的体系结构中使用二进制文件吗?是的,但这只是巧合(或兼容,就像英特尔8085上的英特尔8080)

    • 你一直声称用C编写的程序可以被其他人在他们的计算机上使用而不会出现问题。只有在SPARC工作站上运行Windows,而不是Linux或OS X、OpenBSD或Solaris时,才会出现这种情况

      在其他操作系统上显示windows或进行网络I/O(“ping google.com”)时必须使用的C库是不同的。尤其是
      ping
      是一种非常不可移植的东西,因为发送ICMP回显请求数据包通常是一种特权操作。(例如,Linux上的
      ping
      可执行文件是setuid root,因此它可以强制执行速率限制。)您可能会使用
      系统(“ping google.com”)
      而不是在自己的程序中使用网络套接字。更好的例子是发出HTTP请求,因为任何进程都可以打开TCP连接

      你可以编写可移植的C程序,但你必须努力使它们可移植。人们需要源代码,这样他们就可以为自己的系统编译它。(这就是为什么Unix有以源代码形式分发软件的传统:每个人都需要用自己版本的库为自己的系统编译软件。)

      编译的二进制文件只能在编译它们的目标平台上工作,例如x86-64 Windows。这样的二进制文件在ARM Windows或仅32位的x86 Windows上不起作用


      在asm中编写时,源代码特定于目标平台(包括CPU,而不仅仅是可用的系统调用和库)。因此,您将为32位x86 Windows编写代码,而不仅仅是“for Windows”,因为C编译器能够从同一源代码生成x86 32位或x86-64位二进制代码

      如果您首先关心的是32位x86 Windows,那么差别不大。(每台“普通”Windows计算机都可以运行32位x86二进制文件,因此,如果您想移植到其他Windows计算机上,就应该这样做。)

      例如,让我们使用查看一个普通的C程序如何为两个不同的x86平台编译为不同的asm:

      #include <stdio.h>
      int main() { puts("Hello World"); }
      
      但MSVC for 32位x86 Windows将其编译为以下asm:

      $SG5328 DB        'Hello World', 00H
      EXTRN   _puts:PROC
      _main   PROC
          push     OFFSET $SG5328
          call     _puts                    ; first arg passed on the stack
          add      esp, 4                   ; clean up args
          xor      eax, eax                 ; eax = 0 = return value.
          ret      0
      _main   ENDP
      
      汇编程序语法是不同的(MASM与GAS),但这不是最重要的。重要的是,指向字符串文本的指针在堆栈上传递(使用
      push
      ),而不是在寄存器中传递

      在Windows上,
      puts
      的asm符号名称的前缀是
      \uu
      ,但在Linux上不是

      由于这是32位代码,堆栈槽的宽度只有4字节,而不是8字节

      这适用于两种平台上都可用的ISO C函数,如
      puts
      。在Windows上,您可以在WinAPI DLL中调用
      MessageBoxA
      ,但Linux没有“本机”图形API。大多数台式机都需要X11库,但并非所有人都使用X11


      因为您已经了解C,所以查看编译器输出是开始学习asm的一个好方法参见马特·戈博尔特的CppCon2017演讲
      $SG5328 DB        'Hello World', 00H
      EXTRN   _puts:PROC
      _main   PROC
          push     OFFSET $SG5328
          call     _puts                    ; first arg passed on the stack
          add      esp, 4                   ; clean up args
          xor      eax, eax                 ; eax = 0 = return value.
          ret      0
      _main   ENDP