Assembly 如何在不使用库的情况下创建汇编程序?

Assembly 如何在不使用库的情况下创建汇编程序?,assembly,libraries,nasm,Assembly,Libraries,Nasm,我只是刚刚开始学习汇编语言。我正在Windows Vista上使用NASM汇编程序 通常,当我开始学习一门新语言时,我会复制别人的Hello World代码,并尝试逐行理解它。然而,我发现很难找到一个不引用其他库的Hello World程序!你看,如果每一行代码都与整个附加代码库紧密相连,那么试图理解每一行代码是没有意义的 我想学习汇编的原因之一是,我可以几乎完全控制我编写的程序。我不想依赖任何图书馆 所以我的问题是:有人能给我一个完全独立的Hello World程序的NASM兼容汇编代码,这个

我只是刚刚开始学习汇编语言。我正在Windows Vista上使用NASM汇编程序

通常,当我开始学习一门新语言时,我会复制别人的Hello World代码,并尝试逐行理解它。然而,我发现很难找到一个不引用其他库的Hello World程序!你看,如果每一行代码都与整个附加代码库紧密相连,那么试图理解每一行代码是没有意义的

我想学习汇编的原因之一是,我可以几乎完全控制我编写的程序。我不想依赖任何图书馆

所以我的问题是:有人能给我一个完全独立的Hello World程序的NASM兼容汇编代码,这个程序可以输出到Windows Vista控制台吗

或者,我理解可能需要一个库来告诉pogram在哪里打印输出,即Windows控制台。除此之外,我不明白为什么需要任何库。我忽略了什么吗?

就是这样:

不过,您不能随便使用操作系统功能。不使用库(如C库)的缺点是您将自己耦合到特定的操作系统。

是如何:


不过,您不能随便使用操作系统功能。不使用库(如C库)的缺点是,您将自己耦合到特定的操作系统。

Windows为所有程序加载kernel32.dll和ntdll.dll库,而与您是否在系统上使用它们无关。您必须使用它们,因为操作系统的低级接口取决于您的处理器及其版本,也就是说,在某些windows更新之后,它可能会更改。

windows为所有程序加载kernel32.dll和ntdll.dll库,而与您是否在windows上使用它们无关。您必须使用它们,因为操作系统的低级接口取决于您的处理器及其版本,也就是说,在一些windows更新之后,它可能会发生更改。

作为替代方法,您可以编写引导加载程序,直接通过视频内存将Hello,World打印到控制台。那么你和裸金属之间几乎什么都没有。您可以找到指向的引导加载程序的制作说明。从阅读该页开始,对概念和想法进行解释。之后,通过外部链接访问。请注意,那里的教程使用BIOS a库打印消息。但是,您可以在OSDev Wiki上搜索有关如何在不使用BIOS的情况下将消息打印到屏幕上并进行所需更改的信息

编辑以添加:


我强烈建议您为此活动使用某种虚拟化。除非你真的知道自己在做什么,否则不要乱动硬盘上的引导扇区。

作为替代方法,你可以编写一个引导加载程序,直接通过视频内存将Hello,World打印到控制台。那么你和裸金属之间几乎什么都没有。您可以找到指向的引导加载程序的制作说明。从阅读该页开始,对概念和想法进行解释。之后,通过外部链接访问。请注意,那里的教程使用BIOS a库打印消息。但是,您可以在OSDev Wiki上搜索有关如何在不使用BIOS的情况下将消息打印到屏幕上并进行所需更改的信息

编辑以添加:


我强烈建议您为此活动使用某种虚拟化。除非你真的知道自己在做什么,否则不要乱动硬盘上的引导扇区。

Windows的设计使所有东西都在一个库中。最基本的库是Kernel32.dll,它包括用于写入和读取文件以及其他非常基本的操作的函数。写入控制台实际上只是写入一个特殊的文件

在Linux上,基本系统函数不在库中,而是在通过中断80访问的系统调用中。因此,在Linux上,完全不需要任何库调用就可以编写一些相当高级的程序,而且非常容易


但是,您可能应该接受一些库。图书馆的全部目的就是让你的生活更轻松。继续使用C标准库,这样您就可以拥有一些基本的控制台和文件输入/输出。从那里,你可能找不到任何真正需要你自己制作的库的地方。

Windows的设计使所有东西都在一个库中。最基本的库是Kernel32.dll,它包括用于写入和读取文件以及其他非常基本的操作的函数。写入控制台实际上只是写入一个特殊的文件

在Linux上,基本系统函数不在库中,而是在通过中断80访问的系统调用中。T hus,在Linux上,编写一些相当高级的程序而不需要任何库调用是可能的,而且非常容易


但是,您可能应该接受一些库。图书馆的全部目的就是让你的生活更轻松。继续使用C标准库,这样您就可以拥有一些基本的控制台和文件输入/输出。从那里,你可能找不到任何真正需要你自己制作的图书馆。

谢谢你的快速回复。不幸的是,NASM几乎在每一行都发现了语法错误,我认为这是因为上面是AT&T语法,NASM需要Intel语法。请参阅您链接到的Wikibooks页面上的General Information部分。你或其他人知道如何转换这个吗?如果我能让转换后的版本正常工作,我的下一个问题是:哪些行/短语与操作系统相关?对_GetStdHandle@4及_WriteFile@20是特定于操作系统的。就像前面、中间和后面的所有线条一样。基本上,除去.ascii指令的整个文件是特定于操作系统的。主要功能是操作系统要求。堆栈帧设置和拆卸是操作系统的要求。操作系统要求在每次函数调用之前在堆栈上推送参数。所以,基本上,除了一行之外,所有的都是操作系统的要求。转换并不像看上去那么难。只需在大多数指令上删除l并切换操作数的顺序即可。删除$和%。因此,“subl$4,%esp”变为“sub-esp,4”。LEA有点奇怪,它变成了LEA ebx,[ebp+4]。谢谢SoapBox。我现在只得到3个错误,从第1行开始:尝试在任何非本地标签之前定义本地标签。我没有改变约翰最初的回答。我应该吗?啊哈!我刚刚安装了MinGW,并让Johannes的代码在遵循他链接的Wikibooks教程后工作。我在使用NASM方面也取得了进展,使用了不同于的代码,并且它不调用任何外部子例程!这是否意味着它不使用任何库?谢谢您的快速回复。不幸的是,NASM几乎在每一行都发现了语法错误,我认为这是因为上面是AT&T语法,NASM需要Intel语法。请参阅您链接到的Wikibooks页面上的General Information部分。你或其他人知道如何转换这个吗?如果我能让转换后的版本正常工作,我的下一个问题是:哪些行/短语与操作系统相关?对_GetStdHandle@4及_WriteFile@20是特定于操作系统的。就像前面、中间和后面的所有线条一样。基本上,除去.ascii指令的整个文件是特定于操作系统的。主要功能是操作系统要求。堆栈帧设置和拆卸是操作系统的要求。操作系统要求在每次函数调用之前在堆栈上推送参数。所以,基本上,除了一行之外,所有的都是操作系统的要求。转换并不像看上去那么难。只需在大多数指令上删除l并切换操作数的顺序即可。删除$和%。因此,“subl$4,%esp”变为“sub-esp,4”。LEA有点奇怪,它变成了LEA ebx,[ebp+4]。谢谢SoapBox。我现在只得到3个错误,从第1行开始:尝试在任何非本地标签之前定义本地标签。我没有改变约翰最初的回答。我应该吗?啊哈!我刚刚安装了MinGW,并让Johannes的代码在遵循他链接的Wikibooks教程后工作。我在使用NASM方面也取得了进展,使用了不同于的代码,并且它不调用任何外部子例程!这是否意味着它不使用任何库?一个相互询问的建议-谢谢,我会尝试一下。我的首要任务仍然是让它在Windows上运行,所以我欢迎更多的答案。如果你在Windows下运行,你将使用库。实际上,您将使用覆盖在库层之上的库层。你不仅在循环中有kernel32.dll和ntdll.dll,还有他们加载的任何库,它们现在懒得检查它们,还有HAL和任何涉及的设备驱动程序,在这种情况下,它们至少会涉及到你的视频设备驱动程序。哦,不用担心引导扇区的东西。我很清楚这种危险,并且有一台旧的备用机器用于这种试验:一个相互询问的建议——谢谢,我会试试看。我的首要任务仍然是让它在Windows上运行,所以我欢迎更多的答案。如果你在Windows下运行,你将使用库。实际上,您将使用覆盖在库层之上的库层。你不仅在循环中有kernel32.dll和ntdll.dll,还有他们加载的任何库,它们现在懒得检查它们,还有HAL和任何涉及的设备驱动程序,在这种情况下,它们至少会涉及到你的视频设备驱动程序。哦,不用担心引导扇区的东西。我很清楚这些危险,并且有一台旧的备用机器来进行这种试验:当然,只有当我的代码中有一行引用了一个例程时,我才会真正使用它们
他们是谁?那么,上面答案中的代码在任何时候都是指他们吗?是的,是的。不,不管你的代码是什么,你都会使用它们——Windows为所有程序加载kernel32.dll和ntdll.dll库。当然,只有当我的代码中有一行引用了其中的例程时,我才会真正使用它们?那么,上面答案中的代码在任何时候都是指他们吗?是的,是的。不,无论您的代码是什么,您都将使用它们-Windows为所有程序加载kernel32.dll和ntdll.dll库。系统调用只是库的一个实现细节。不管是通过中断门还是通过另一种保护门的存根函数来完成,这都是无关紧要的:您仍然在使用库。好的,如果需要一个库文件来写入控制台,我很乐意接受它。目前,我只想输出hello world。参考Ha的回答和评论,这个Kernel32.dll库似乎已经在Johannes代码中使用,所以我将继续尝试将其转换并工作。系统调用只是库的一个实现细节。不管是通过中断门还是通过另一种保护门的存根函数来完成,这都是无关紧要的:您仍然在使用库。好的,如果需要一个库文件来写入控制台,我很乐意接受它。目前,我只想输出hello world。参考HA的回答和评论,看起来这个KRNEL32.DLL库已经在约翰尼斯代码中使用,所以我将继续尝试并将其转换和工作。考虑在没有操作系统的情况下,在一些基于微控制器的系统上学习汇编。比如说,一块基于AVR的裸板。除了你的代码外,这些代码上不会有任何代码。您可能会从打开LED开始,因为在这一点上,您的技能还不足以为连接的终端仿真器编写串行输入/输出例程。作为一个中间人,你可以想象LED灯闪烁时会发出“你好,世界!”!在莫尔斯。这是一个伟大的想法@Bushmills,谢谢。我最初的帖子是4年前写的,只是出于教育目的,所以从那以后我就再也没看过汇编了。但是你的建议听起来很有趣。我不知道“基于AVR的板”-你能把我和你所指的那种东西联系起来吗?有很多低成本的板。如果你不介意瓷器,看看在线零售商,在那里你可以花10美元或更少的钱买到完整的板子。例如,arduino克隆——对于那些你甚至不需要flash编程器的产品,因为它们可以连接到USB,这仅仅是闪存控制器中已有一些软件的结果。如果你这么想的话,更有趣的是得到一个试验板和一些组件,然后自己把你的控制器板插在一起——但需要一个设备将你的程序实际加载到控制器中。我喜欢低成本的arduino nano克隆。ATMega32和更高版本是我选择的-它们有足够的板载资源在控制器上运行编程语言。Forth对微控制器来说很好。对于ATMEGA16和以下,空间有点紧,这样的应用程序,但仍然有大量的纯装配编码。考虑学习汇编在一些微控制器的系统没有操作系统。比如说,一块基于AVR的裸板。除了你的代码外,这些代码上不会有任何代码。您可能会从打开LED开始,因为在这一点上,您的技能还不足以为连接的终端仿真器编写串行输入/输出例程。作为一个中间人,你可以想象LED灯闪烁时会发出“你好,世界!”!在莫尔斯。这是一个伟大的想法@Bushmills,谢谢。我最初的帖子是4年前写的,只是出于教育目的,所以从那以后我就再也没看过汇编了。但是你的建议听起来很有趣。我不知道“基于AVR的板”-你能把我和你所指的那种东西联系起来吗?有很多低成本的板。如果你不介意瓷器,看看在线零售商,在那里你可以花10美元或更少的钱买到完整的板子。例如,arduino克隆——对于那些你甚至不需要flash编程器的产品,因为它们可以连接到USB,这仅仅是闪存控制器中已有一些软件的结果。如果你这么想的话,更有趣的是得到一个试验板和一些组件,然后自己把你的控制器板插在一起——但需要一个设备将你的程序实际加载到控制器中。我喜欢低成本的arduino nano克隆。ATMega32和更高版本是我选择的-它们有足够的板载资源在控制器上运行编程语言。Forth对微控制器来说很好。对于ATMega16及以下版本,此类应用程序的空间有点紧,但对于纯汇编代码来说仍然足够。
       .text
LC0:
        .ascii "Hello, world!\12"
.globl _main
_main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $4, %esp
        pushl   $-11
        call    _GetStdHandle@4
        pushl   $0
        leal    -4(%ebp), %ebx
        pushl   %ebx
        pushl   $14
        pushl   $LC0
        pushl   %eax
        call    _WriteFile@20
        movl    $0, %eax
        leave
        ret