我的汇编器中出现段错误?但这是不可能的! :哦

发布于 2024-09-12 22:35:33 字数 585 浏览 8 评论 0原文

好吧,我知道我们所有的 C/C++ 程序员都曾经遇到过我们不合时宜的克星,恶魔信号 SIGSEGV,即分段错误。现在,我明白(强调过去时态)这是由神奇的 GCC(或 g++)编译器或其他编译器吐出的机器代码的某些部分中某种形式的故障安全/检查系统。

但!今天,我在虚拟化的 Arch Linux 系统上使用一些旧式 NASM 的 x86 汇编器搞砸了,令我惊讶和懊恼的是,我的编码工作再次受到邪恶的 SegFault 的阻碍。

下面是产生可怕信号的代码:

mov eax, 0x7
mov [0xB8000], eax

现在,我知道 Linux 内核将汇编的程序加载到 shell 中并从那里执行它,但我认为这个 MOV 指令与处理器进行 1 对 1 的交互,到底如何才能内核检测到我正在尝试访问它不希望我访问的内存位,并停止指令?

我不会假装理解当你的程序被加载到 shell 中时到底发生了什么,你在 shell 中拥有什么权限,甚至 shell 是什么或者它是如何工作的,但我曾经确信 ASM 给了你对处理器的完全控制。这个神奇的内核如何干扰我对处理器的直接命令,为什么我在编写本质上纯机器代码时仍然被迫经历这个操作系统命令链? :哦

Okay, so I understand all of us C/C++ programmers have at one time met our untimely nemesis, the diabolical signal SIGSEGV, the Segmentation Fault. Now, I understood (emphasis on the past tense) this to be some form of fail safe / checking system within some portion of the machine code spat out by the magical GCC (or g++) compiler, or what have you.

But! Today I was screwing around with some x86 assembler with good old NASM on a virtualized Arch Linux system, and much to my surprise and chagrin, was once again thwarted in my coding efforts by the nefarious SegFault.

Here is the code that spawned the dreaded signal:

mov eax, 0x7
mov [0xB8000], eax

Now, I understand that the Linux kernel loads your assembled program into a shell and executes it from there, but I thought this MOV instruction interacted 1 to 1 with the processor, how on Earth can the Kernel detect that I'm trying to access a bit of memory it doesn't want me to, and halt the instruction?

I don't pretend to understand what exactly happens when your program is loaded into a shell, what permissions you have once in the shell, or even what a shell is or how it works, but I used to be dang sure that ASM gave you full control over the processor. How does this magical Kernel interfere with my direct commands to the processor, and why am I still forced to go through this chain of Operating System command when writing, essentially, pure machine code? :O

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧人哭 2024-09-19 22:35:33

Linux 执行您的程序正在用户模式 (环 3 位于 x86)。此外,它使用基于页面 内存保护来限制程序可以访问的内存位置。特别是,您的程序尝试写入0xB8000(VGA 帧缓冲区),但它没有修改权限。处理器的 MMU 检测到这一点,并抛出一个 CPU 异常。 Linux 内核处理此异常,并将其转换为段违规信号。假设您尚未为信号设置自定义处理程序,内核将终止您的进程。为了避免这种情况并获得对硬件的完全访问权限,您需要编写一个 Linux 设备驱动程序,该驱动程序将在具有完全权限的内核模式(x86 上的 Ring 0)下运行,或者通过 编写您自己的操作系统

Linux executes your program is running in user-mode (ring 3 on x86). Additionally, it's using page-based memory protection to limit the memory locations your program can access. In particular, your program attempts to write to 0xB8000 (the VGA framebuffer), which it does not have permission to modify. The processor's MMU detects this, and it throws a CPU exception. The Linux kernel handles this exception, and translates it to a segment violation signal. Assuming you haven't set up a custom handler for your signal, the kernel then kills your process. To avoid this and get full access to your hardware, you'll either need to write a Linux device driver which will run in kernel mode (ring 0 on x86) with full permissions, or bypass Linux entirely by writing your own operating system.

冷月断魂刀 2024-09-19 22:35:33

MMU 保护了您尝试访问的内存,因此当您执行违反某些权限的指令时,就会生成中断/处理器异常。该异常由内核处理并作为分段错误信号转发到您的应用程序。由于您的应用程序不处理 SIGSEGV,因此它会终止,并且控制权返回到您的 shell。

如果您想要“完全控制处理器”,则需要在较低级别编写代码(如果您想保持操作系统运行,则在内核中编写,如果您想要,则在您自己的操作系统或执行程序中编写代码)自己处理从启动开始的所有事情)。

编写汇编程序与编写 C 程序没有什么不同,只是您可能会生成一些 C 编译器不会发出的奇怪指令。不会仅仅根据编写程序的语言来授予程序特殊的权限或能力。

The MMU has protected the memory you're trying to access, so when you execute an instruction that violates some permissions, an interrupt/processor exception is generated. That exception is handled by the kernel and forwarded to your application as a segmentation fault signal. Since your application doesn't handle SIGSEGV, it is terminated, and control returned to your shell.

If you want the "full control over the processor" you're looking for, you'll need to write code at a lower level (in the kernel if you want to keep the OS running, or your own OS or executive if you want to handle everything from boot yourself).

Writing an assembly program is no different from writing a C program, except that maybe you can generate some weird instructions your C compiler wouldn't emit. There are no special permissions or abilities granted to a program just based on the language in which it is written.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文