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
,
Дайте мне знать, как это получилось.