I’m trying to write byte 0xff to the parallel port at 0x378. It compiles and links without issue, but segfaults at the OUTSB instruction.
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? or 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
What am I doing wrong here?
(info on the OUTS instructions: http://siyobik.info/main/reference/instruction/OUTS%2FOUTSB%2FOUTSW%2FOUTSD)
EDIT:
The C version of the program works:
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
OUTSBis 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 aSegmentation fault(which is actually aGeneral Protection Faultsignalled by the CPU) when you try to execute a privileged instruction from a nonprivileged segment of code. I don’t know how calling theiopermsyscall influences that, though.Secondly,
OUTSBwrites a byte from a memory location specified byESIto the I/O port inDX. In this case, you’re telling the processor to write data to the port from location0xff, to which the process surely doesn’t have access. You can simplify that by simply changing the code to use theOUTinstruction, sinceOUTSBis rather meant to be used with theREPprefix. Try this :This outputs the byte in
alto the I/O port specified by the immediate operand, in this case0x378.Let me know how that turned out.