SegFaults в моем ассемблере?Но это невозможно!: O - PullRequest
4 голосов
/ 04 августа 2010

Хорошо, я понимаю, что все мы, программисты на C / C ++, когда-то встречали нашего безвременного врага, дьявольского сигнала SIGSEGV, Ошибка сегментации. Теперь я понял (с акцентом на прошедшее время), что это какая-то форма отказоустойчивой / проверяющей системы в некоторой части машинного кода, выдаваемой волшебным компилятором GCC (или g ++), или чем-то еще.

Но! Сегодня я крутился с каким-то ассемблером x86 со старым добрым NASM в виртуализированной системе Arch Linux, и, к моему большому удивлению и огорчению, в очередной раз был сорван в моих усилиях по программированию гнусным SegFault.

Вот код, который породил страшный сигнал:

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

Теперь я понимаю, что ядро ​​Linux загружает вашу собранную программу в оболочку и выполняет ее оттуда, но я думал, что эта инструкция MOV взаимодействует 1: 1 с процессором, как на Земле ядро ​​может обнаружить, что я пытаюсь чтобы получить доступ к части памяти, в которой он не хочет, и остановить инструкцию?

Я не претендую на то, что понимаю, что именно происходит, когда ваша программа загружается в оболочку, какие у вас есть права в ней, или даже что такое оболочка или как она работает, но я был уверен, что ASM дал вам полный контроль над процессором. Как это волшебное Ядро мешает моим прямым командам процессору, и почему я все еще вынужден проходить через эту цепочку команд операционной системы при написании, по сути, чистого машинного кода? : О

Ответы [ 2 ]

4 голосов
/ 04 августа 2010

Linux выполняет вашу программу в режиме пользователя ( звонок 3 на x86 ).Кроме того, он использует на основе страницы защита памяти , чтобы ограничить области памяти, к которым может обращаться ваша программа.В частности, ваша программа пытается записать в 0xB8000 (кадровый буфер VGA), который не имеет разрешения на изменение. MMU процессора обнаруживает это и выдает исключение CPU .Ядро Linux обрабатывает это исключение и преобразует его в сигнал нарушения сегмента .Предполагая, что вы не настроили пользовательский обработчик для своего сигнала, ядро ​​затем убивает ваш процесс.Чтобы избежать этого и получить полный доступ к вашему оборудованию, вам нужно либо написать драйвер устройства Linux, который будет работать в режиме ядра (кольцо 0 на x86) с полными разрешениями, либо полностью обойти Linux, написав собственную операционнуюсистема .

3 голосов
/ 04 августа 2010

MMU защитил память, к которой вы пытаетесь получить доступ, поэтому при выполнении инструкции, которая нарушает некоторые разрешения, генерируется исключение прерывание / процессор. Это исключение обрабатывается ядром и пересылается вашему приложению как сигнал ошибки сегментации. Поскольку ваше приложение не обрабатывает SIGSEGV, оно прекращается, и управление возвращается в вашу оболочку.

Если вы хотите получить «полный контроль над процессором», вам нужно написать код на более низком уровне (в ядре, если вы хотите, чтобы ОС работала, или ваша собственная ОС или исполнительная система). если хочешь сам справиться с загрузкой).

Написание ассемблерной программы ничем не отличается от написания C-программы, за исключением того, что, возможно, вы можете сгенерировать некоторые странные инструкции, которые ваш C-компилятор не будет выпускать. Для программы нет специальных разрешений или возможностей, основанных только на языке, на котором она написана.

...