作为前言,我确实希望被否决而被遗忘,但我不明白这是如何运作的。
我想学习汇编,但我遇到的教程似乎遵循两个方面之一:要么[相对]高水平,要么从头开始构建一切。就我个人而言,我想从头开始学习它是如何工作的,但我翻阅的教程似乎直接进入 64 位版本,你可以在其中编写任何内容。例如:
section .data
hello: db 'Hello world!',10 ; 'Hello world!' plus a linefeed character
helloLen: equ $-hello ; Length of the 'Hello world!' string
section .text
global _start
_start:
mov eax,4 ; The system call for write (sys_write)
mov ebx,1 ; File descriptor 1 - standard output
mov ecx,hello ; Put the offset of hello in ecx
mov edx,helloLen ; helloLen is a constant, so we don't need to say
int 0x80 ; Call the kernel
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return "code" of 0 (no error)
int 80h;
num_to_string:
push ebp
mov ebp, esp
mov esp, ebp
pop ebp
这是一个基本的 hello world 程序,如果我使用 asm 编译器,就会出现该程序。它已经使用了
e_x
寄存器,无需预先写入任何内容。
同时,在一个(可能相当过时的)初学者尝试学习编写引导加载程序并共享它的教程中(youtube播放列表),他必须经历从16位模式到受保护的32位模式,然后到长模式(64位) ).
我知道语法因体系结构而异,但在“裸机”语法和“高级”语法之间,似乎存在明显的差异,不完全是语法,而是编码方式。
我很抱歉无法提供具体的例子,正如我所说,我在一开始,甚至不知道如何开始(并且很困惑,这就是我在这里的原因),所以我希望有人可以请善意地解释发生了什么。
不存在“低级组装”和“高级组装”之说。同一件事放在不同的环境中总是一样的。
例如,您编写的代码大量使用了操作系统(在本例中
int 80h
是对Linux内核的调用),并且您自己不需要做太多事情,因为您只是将一些字符串放入内存中,调用操作系统,就这样,控制台中出现了一个 hello world。
在您提到编写引导加载程序的情况下,您处于一个截然不同的环境中。计算机内存中几乎没有任何内容,您必须通过模式更改等方式来加载完全正常工作的操作系统。 两者的区别仅在于它们所处的环境。当您在操作系统之上运行时,您只是一个调用操作系统的应用程序,而操作系统与硬件通信、管理内存、写入磁盘、处理 CPU 资源和类似。当您编写引导加载程序(或更糟糕的是操作系统)时,您必须自己完成所有这些工作。