Linux NASM OUTSB SegFault - PullRequest
       75

Linux NASM OUTSB SegFault

2 голосов
/ 24 февраля 2012

Я пытаюсь записать байт 0xff в параллельный порт на 0x378.Он компилирует и связывает без проблем, но с ошибками в инструкции OUTSB.

section .text
        global _start

_err_exit:
        mov     eax,    1
        mov     ebx,    1
        int     80h

_start:
        mov     eax,    101     ; ioperm
        mov     ebx,    0x378   ; Parallel port addr
        mov     ecx,    2       ; number of bytes to 'unlock'
        mov     edx,    1       ; enable
        int     80h

        mov     esi,    0xff
        mov     dx,     0x378
        outsb

        mov     eax,    1       ; exit
        mov     ebx,    0
        int     80h

Если я перейду к нему с помощью GDB и проверим регистры непосредственно перед инструкцией OUTSB, это не похоже наесть что-нибудь в регистре DX?или dx == edx в 32-битном?

(gdb) info registers 
eax            0x0  0
ecx            0x2  2
edx            0x378    888
ebx            0x378    888
esp            0xffffd810   0xffffd810
ebp            0x0  0x0
esi            0xff 255
edi            0x0  0
eip            0x8048090    0x8048090 <_start+36>
eflags         0x246    [ PF ZF IF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x0  0

Что я здесь не так делаю?

(информация о инструкциях OUTS: http://siyobik.info/main/reference/instruction/OUTS%2FOUTSB%2FOUTSW%2FOUTSD)


РЕДАКТИРОВАТЬ:

C версия программы работает:

int main(int argc, char *argv[])
{
  int addr = 0x378;
  int result = ioperm(addr,5,1);

  outb(0xff, addr);

}

1 Ответ

4 голосов
/ 24 февраля 2012

Существует ряд проблем с этим кодом. Во-первых, вы, кажется, забыли, что OUTSB является привилегированной инструкцией, то есть она может быть выполнена, только если вызывающий процесс имеет доступ к кольцу 0, т.е. это часть кода ядра. Насколько я знаю, единственным кодом в Linux, который имеет доступ к привилегированным инструкциям, является само ядро ​​и загружаемые им модули. Все остальные процессы выдадут вам Segmentation fault (что на самом деле General Protection Fault сигнализируется процессором), когда вы попытаетесь выполнить привилегированную инструкцию из непривилегированного сегмента кода. Я не знаю, как это влияет на вызов ioperm системного вызова.

Во-вторых, OUTSB записывает байт из области памяти, указанной в ESI, в порт ввода-вывода в DX. В этом случае вы говорите процессору записывать данные в порт из местоположения 0xff, к которому процесс, безусловно, не имеет доступа. Вы можете упростить это, просто изменив код для использования инструкции OUT, поскольку OUTSB скорее предназначен для использования с префиксом REP. Попробуйте это:

mov al, 0xff
out 0x378, al

Это выводит байт в al на порт ввода-вывода, указанный непосредственным операндом, в данном случае 0x378.

Дайте мне знать, как это получилось.

...