我有一个简单的程序,必须阅读PCI configuration space
(仅适用于第一个PCI设备)。但它不起作用。
YASM:
18: warning: value doesnt fit in 8 bit fild
19: warning: value doesnt fit in 8 bit fild
以下是代码:
[use 32]
[org 0x7c00]
start:
mov ah, 0x3
int 0x10 ;clear screen
;forming the PCI address
push ax
or ah, 10000000b
xor al, al
or al, 00000001b
shl eax, 16
pop ax
xor al, al
xor ah, ah
push eax
out 0xcf8, eax
in eax, 0xcfc
mov edi, field
stosd
mov si, di
call print_str
ret
field:
print_str:
;print a string in si
mov ax, 0xb800
mov es, ax
xor di, di
mov cx, 128
rep movsw
ret
times 510 - ($ - $$) db 0
dw 0xaa55
感谢。
P.S。我正在使用Bochs进行仿真,使用YASM作为汇编程序
答案 0 :(得分:3)
您不能将out
或in
与16位立即端口号一起使用。 in
和out
只能使用8位立即端口号。
因此您需要将端口号存储到dx
:
mov dx,0xcf8 out dx,eax in eax,dx
然后,在下面的块中有几个问题:
mov edi,field stosd mov si, di call print_str ret field: print_str: ;print a string in si mov ax, 0xb800 mov es, ax xor di, di mov cx, 128 rep movsw ret
编辑:修正了拼写错误,应该是:“不要保留”。校正。
上面的块有几个问题。首先,我假设你想使用edi
作为内存的索引,在哪里存储东西。但是,由于您没有为此目的保留任何内存,因此您很高兴使用从端口mov ax,0xb800
读取到66 b8 00 b8
的值覆盖eax
(0xcf8
,正好为4个字节) (如果您首先修复了直接的16位端口号。)
其次,我不确定在引导加载程序代码中默认指向es
的位置,无论如何,可能需要先将其设置为:
push cs pop es
保留记忆:
field: times 4 db 0 ; to reserve 4 bytes (but you may need more, ; keep reading to understand why)
但这仍然不够。如果您要将0xcfc
中的数字打印到eax
rep movsw
,您需要先将其转换为字符串。将数字转换为x86程序集中的字符串(十进制或十六进制)在SO中经常被问到,所以请检查一些以前的答案以获得想法:
Is this code correct (Number plus number, then print the result)
请注意,您需要的字节数与数字中的字符数一样多,如果您想使用rep movsw
,则需要2 x字符数。(参见下文)。
然后在用于写入视频内存的代码中,您似乎将二进制值复制到视频内存而不进行任何转换。因此,在完成上述2个修复后,您可能会在第一行的前64个字符中获得一些彩色字符。请参阅my recent answer to a SO question on printing a string without OS,它有示例代码,有两种不同的方法。
希望这有帮助。