Linux NASM OUTSB SegFault

Я пытаюсь написать байт 0xff к параллельному порту в 0x378, Он компилирует и ссылки без проблем, но segfaults на 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 ответ

Решение

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

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

mov al, 0xff
out 0x378, al

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

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

Другие вопросы по тегам