我正在尝试通过内联汇编代码中的IN和OUT指令从Linux(Ubuntu)上的C访问I / O端口。执行IN或OUT指令后立即生成seg故障。
例如,这段简单的代码会生成一个seg错误:
#include <stdint.h>
int main() {
uint8_t readvalue = 0;
uint16_t port = 0xB3;
asm volatile("in %%dx, %%al\n\t"
: "=a" (readvalue)
: "d" (port)
);
return(0);
}
我编译:gcc -O2 -g
从GDB,我看到这个程序被编译成以下简单的汇编代码序列:
mov $0xb3,%edx
in (%dx),%al
xor %eax,%eax
retq
在GDB中,我看到只要执行IN指令,就会发生seg故障。
完整的GDB会话:
(gdb) list
1 #include <stdint.h>
2
3 int main() {
4
5 uint8_t readvalue = 0;
6 uint16_t port = 0xB3;
7
8 asm volatile("in %%dx, %%al\n\t"
9 : "=a" (readvalue)
10 : "d" (port)
(gdb) list
11 );
12
13 return(0);
14
15 }
16
(gdb) break 7
Breakpoint 1 at 0x4003e0: file tcgsmi_inonly_pure.c, line 7.
(gdb) r
Starting program: /home/emerald/tcgsmi_inonly_pure
Breakpoint 1, main () at tcgsmi_inonly_pure.c:8
8 asm volatile("in %%dx, %%al\n\t"
(gdb) disass
Dump of assembler code for function main:
=> 0x00000000004003e0 <+0>: mov $0xb3,%edx
0x00000000004003e5 <+5>: in (%dx),%al
0x00000000004003e6 <+6>: xor %eax,%eax
0x00000000004003e8 <+8>: retq
End of assembler dump.
(gdb) display/i $rip
1: x/i $rip
=> 0x4003e0 <main>: mov $0xb3,%edx
(gdb) ni
0x00000000004003e5 8 asm volatile("in %%dx, %%al\n\t"
1: x/i $rip
=> 0x4003e5 <main+5>: in (%dx),%al
(gdb) ni
Program received signal SIGSEGV, Segmentation fault.
0x00000000004003e5 in main () at tcgsmi_inonly_pure.c:8
8 asm volatile("in %%dx, %%al\n\t"
1: x/i $rip
=> 0x4003e5 <main+5>: in (%dx),%al
答案 0 :(得分:1)
答案在OP的评论中。
不能简单地在用户模式下访问IO端口。
ioperm()的原型是:
int ioperm(unsigned long from, unsigned long num, int turn_on);
from =您要访问的端口范围的ID
num =范围长度
turn_on =非零以启用访问,零以禁用访问
因此,在上面的示例中,调用将是:
ioperm(0xB3,1,1);