为什么 mov rax,cr0 在 nasm 64 位中导致段错误

Why does mov rax,cr0 cause a segmentation fault in nasm 64 bit

我需要编写代码来测试 nasm 中 cr0 的 LSB。代码如下:

section .data
temp : db 00h   ;Temporary storage
nl : db 10      ;Memory which holds decimal 10 to print a newline 

section .text
global _start
_start:
mov rax,cr0        ;Move contents of cr0 into rax
bt rax,0           ;Test LSB of rax 
jnc l1             ;If 0, move 30 into temp (ASCII for '0')  
mov byte[temp],31h ;Else, move 31 into temp
jmp l2
l1:
mov byte[temp],30h
l2:
print temp,1       ;Print value of temp
print nl,1

mov rax,60         ;Exit syscall
mov rdi,0
syscall

当 运行 时,代码会导致分段错误。它的发生是因为指令 mov rax,cr0。当注释该指令时,不会发生分段错误。为什么会这样?这与用户的权限级别有关吗?提前致谢。

您正试图在不处于特权模式时执行特权指令。
根据 instruction set reference:

Protected Mode Exceptions
#GP(0) If the current privilege level is not 0.

因为您运行处于用户模式,所以您不能运行特权指令。

要进入实模式,您必须首先在 ring 0 中获得特权级别。
为此,您必须在内核模式下执行。
请参阅 fuz's answer 了解如何在 Linux 中执行此操作。

有关进入和退出实模式的详细信息,请参阅:https://www.codeproject.com/articles/45788/the-real-protected-long-mode-assembly-tutorial-for

代替mov rax,cr0,您可以使用smsw instruction来存储cr0的低16位。此指令没有特权,适用于所有环:

smsw ax
test ax,1
jnz protected_mode