2017-01-29 24 views
1

Мне нужно было написать код для проверки LSB cr0 в nasm. Код выглядит следующим образом:Почему mov rax, cr0 вызывает ошибку сегментации в nasm 64 бит

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. Когда эта команда прокомментирована, не возникает ошибка сегментации. Почему это так? Связано ли это с уровнем привилегий пользователя? Заранее спасибо.

+2

Да, точно. 'CR0' - системный регистр, недоступный в пользовательском режиме. Если вы обратитесь к руководству по набору инструкций, вы увидите, что он говорит: Исключения для 64-битного режима #GP (0) Если текущий уровень привилегий не равен 0._ – Jester

+0

Любое обходное решение этой проблемы? Или мое направление мышления неверно? @Jester –

+0

Что вы хотите делать с содержимым 'cr0'? – fuz

ответ

2

Вместо mov rax,cr0, вы можете использовать smsw instruction для хранения низкой 16 бит cr0. Эта инструкция не имеет привилегий и работает на всех кольцах:

smsw ax 
test ax,1 
jnz protected_mode 
+0

Вы пропустили крошечную маленькую деталь: _ можно использовать в прикладных программах, если CR4.UMIP = 0._ – Jester

+0

@Jester. Если быть честным, я не думаю, что какие-либо процессоры, на самом деле реализующие UMIP, еще не выпущены. –

+1

Это может быть, но ясно, что эта лазейка тоже закрывается;) Теперь это может сработать. – Jester

0

Вы пытаетесь выполнить привилегированную инструкцию, пока вы не находитесь в привилегированном режиме.
Согласно instruction set reference:

Исключения защищенного режима
#GP (0) Если текущий уровень привилегий не 0.

Поскольку вы работаете в пользовательском режиме вы не можете запустить привилегированные инструкции ,

Для входа в реальный режим вы должны сначала получить уровень привилегий в кольце 0.
Для того, чтобы это произошло, вы должны выполняться в режиме ядра.
См. fuz's answer о том, как это сделать в Linux.

Для получения дополнительной информации о входе и выходе из реального режима см: https://www.codeproject.com/articles/45788/the-real-protected-long-mode-assembly-tutorial-for

 Смежные вопросы

  • Нет связанных вопросов^_^