Can*_*niz 1 linux x86 assembly segmentation-fault
使用第 7 代 i5 处理器,nasm,ld。
该程序使用通用寄存器和系统调用编写,可在 Ubuntu 上运行。一个例子是一个简单的 hello world 程序。
global _start
section .text
_start:
mov eax, 0x4 ; write(int fd, char *buf, int len)
mov ebx, 0x1 ; fd
mov ecx, message ; *buf
mov edx, message_length ; len
int 0x80 ; syscall
mov eax, 0x1 ; exit(int status)
mov ebx, 0x0 ; status
int 0x80 ; syscall
section .data
message db "hello world", 0xA
message_length equ $-message
Run Code Online (Sandbox Code Playgroud)
nasm -f elf64 -o hello_world.o hello_world.s
ld hello_world.o -o hello_world
./hello_world
Run Code Online (Sandbox Code Playgroud)
输出: hello_world
但是,使用intel 系统指令编写的程序不起作用。
global _start
section .text
_start:
CLI
HLT
Run Code Online (Sandbox Code Playgroud)
nasm -f elf64 halt.s -o halt.o
ld halt.o -o halt
./halt
Run Code Online (Sandbox Code Playgroud)
输出: Segmentation fault (core dumped)
你有两个问题:
是什么阻止了这段代码以这种方式编译和运行?
没有什么可以阻止它组装,因为它是有效的代码。
其原因不运行/抛出一个segmentation fault的是,你正试图运行需要在用户模式下某些特权指令。
看看描述说明的HLT
HLT 指令是特权指令。
也看看CLI /STI,它的情况更复杂(在下面的文章和下面的评论中解释),但也主要用于内核模式代码。维基百科说
在所有三种情况下,只有特权应用程序(通常是操作系统内核)可以修改 IF[Interrupt flag]。[...] CLI 和 STI [也是] 特权指令,如果非特权应用程序尝试执行它,则会触发一般保护错误,[...]
这应该可以回答您关于这两条指令之间的区别以及为什么HLT肯定会生成在User Mode 中执行的 GPF (General Protection Fault) 的问题。
这段代码如何编译和运行?
运行此代码的唯一方法是在特权模式下。因此,在 Windows 或 Linux 上,您必须编写内核驱动程序或编写自己的操作系统代码才能合理使用这些指令。
以上仅适用于保护模式或长模式代码。
(实模式代码可能总是修改 IF,中断标志)