简体   繁体   English

Linux NASM OUTSB SegFault

[英]Linux NASM OUTSB SegFault

I'm trying to write byte 0xff to the parallel port at 0x378 . 我正在尝试将字节0xff写入并行端口0x378 It compiles and links without issue, but segfaults at the OUTSB instruction. 它可以毫无问题地进行编译和链接,但是会在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

If I step through it with GDB and check the registers just before the OUTSB instruction, it doesn't look like there is anything in the DX register? 如果我使用GDB逐步检查并检查OUTSB指令之前的寄存器,那么看起来DX寄存器中没有任何内容吗? or dx == edx in 32bit? 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

What am I doing wrong here? 我在这里做错了什么?

(info on the OUTS instructions: http://siyobik.info/main/reference/instruction/OUTS%2FOUTSB%2FOUTSW%2FOUTSD ) (有关OUTS指令的信息: http ://siyobik.info/main/reference/instruction/OUTS%2FOUTSB%2FOUTSW%2FOUTSD)


EDIT: 编辑:

The C version of the program works: 该程序的C版本有效:

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

  outb(0xff, addr);

}

There is a number of issues with that code. 该代码存在许多问题。 Firstly, you seem to forget that OUTSB is a privileged instruction, ie it can be executed only if the calling process has ring 0 access, ie it's a part of the kernel code. 首先,您似乎忘记了OUTSB是特权指令,即只有在调用进程具有ring 0访问权限(即它是内核代码的一部分)时才能执行。 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. 据我所知,Linux中唯一可以访问特权指令的代码是内核本身及其加载的模块。 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. 当您尝试从非特权代码段执行特权指令时,所有其他进程都会给您带来Segmentation fault (实际上是CPU发出的General Protection Fault )。 I don't know how calling the ioperm syscall influences that, though. 不过,我不知道调用ioperm syscall会如何影响这一点。

Secondly, OUTSB writes a byte from a memory location specified by ESI to the I/O port in DX . 其次, OUTSBESI指定的存储位置向DX的I / O端口写入一个字节。 In this case, you're telling the processor to write data to the port from location 0xff , to which the process surely doesn't have access. 在这种情况下,您要告诉处理器将数据从位置0xff写入端口,该进程肯定无法访问该位置。 You can simplify that by simply changing the code to use the OUT instruction, since OUTSB is rather meant to be used with the REP prefix. 您可以通过简单地更改代码以使用OUT指令来简化此操作,因为OUTSB而是与REP前缀一起使用的。 Try this : 尝试这个 :

mov al, 0xff
out 0x378, al

This outputs the byte in al to the I/O port specified by the immediate operand, in this case 0x378 . 它将al的字节输出到立即操作数指定的I / O端口,在这种情况下为0x378

Let me know how that turned out. 让我知道结果如何。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM