2012-02-23 65 views
2

我正在嘗試將字節0xff寫入並口0x378。它編譯和鏈接沒有問題,但段錯誤在OUTSB指令。Linux NASM OUTSB SegFault

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 in 32bit?

(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); 

} 

回答

4

有一些問題與代碼。首先,你似乎忘記了OUTSB是一條特權指令,即它只有在調用進程具有ring 0訪問時才能執行,即它是內核代碼的一部分。據我所知,Linux中唯一可以訪問特權指令的代碼是內核本身以及它加載的模塊。當您嘗試從非特權代碼段執行特權指令時,所有其他進程將給您一個Segmentation fault(實際上是由CPU發送信號的General Protection Fault)。不過,我不知道如何調用ioperm系統調用。

其次,OUTSB將一個字節從ESI指定的存儲位置寫入DX的I/O端口。在這種情況下,您告訴處理器將數據寫入端口0xff的端口,該進程肯定無法訪問該端口。只需更改代碼以使用OUT指令即可簡化該操作,因爲OUTSB更適用於REP前綴。嘗試:

mov al, 0xff 
out 0x378, al 

al輸出字節通過立即操作數中指定的I/O端口,在這種情況下0x378

讓我知道結果如何。

+0

另一個說明:我只是修改了一些英特爾手冊,顯然可以將單個I/O端口的權限授予單個任務。這需要在操作系統中使用TSS(任務狀態段)結構,我不確定Linux是否將它用於每個單獨的進程。 – 2012-02-24 00:44:19

+0

'OUT'與'OUTS *'一樣享有特權,將另一個替換爲另一個不會解決主要問題。 – 2012-02-24 00:48:02

+1

我知道。但在這種情況下,'OUTSB'使用不當,因爲它會導致從內存區域讀取,這絕對不在進程的地址空間中。 – 2012-02-24 06:22:57