2

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== edx32ビットで?

(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

1 に答える 1

4

There is a number of issues with that code. Firstly, you seem to forget that OUTSB is a privileged instruction, i.e. it can be executed only if the calling process has ring 0 access, i.e. it's a part of the kernel code. As far as I'm aware, the only code in Linux that has access to privileged instructions is the kernel itself, and the modules that it loads. All the other processes will give you a Segmentation fault (which is actually a General Protection Fault signalled by the CPU) when you try to execute a privileged instruction from a nonprivileged segment of code. I don't know how calling the ioperm syscall influences that, though.

次に、 で指定されたメモリ位置からバイトを の I/O ポートにOUTSB書き込みます。この場合、プロセスが確実にアクセスできない location からポートにデータを書き込むようにプロセッサに指示しています。命令を使用するようにコードを変更するだけで簡単にすることができます。これを試して :ESIDX0xffOUTOUTSBREP

mov al, 0xff
out 0x378, al

alこれにより、即値オペランド (この場合は ) で指定された I/O ポートにバイトが出力されます0x378

それがどうなったか教えてください。

于 2012-02-24T00:38:32.943 に答える