Question

I have a simple program, that must read PCI configuration space (just for first PCI device). But it doesnt works. YASM:

18: warning: value doesnt fit in 8 bit fild
19: warning: value doesnt fit in 8 bit fild

Here is the code:

   [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

Thanks.

P.S. I'm using Bochs for emulation and YASM as assembler

Was it helpful?

Solution

You can't use out or in with 16-bit immediate port numbers. Only 8-bit immediate port numbers are possible for in and out.

So you need to store the port number into dx:

mov     dx,0xcf8
out     dx,eax
in      eax,dx

Then, in the block below there are several issues:

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

Edit: Fixed typo, should be: "don't reserve". Corrected.

The block above has several problems. First, I assume you want to use edi as an index to memory, where to store something. But as you don't reserve any memory for that purpose, you happily overwrite mov ax,0xb800 (66 b8 00 b8, exactly 4 bytes) with the value you read to eax from port 0xcf8 (if you first fixed the immediate 16-bit port numbers).

Second, I'm not exactly sure where es points by default in bootloader code, anyway, it may be necessary to set it first with:

push cs
pop  es

To reserve memory:

field:
times 4 db 0 ; to reserve 4 bytes (but you may need more,
             ; keep reading to understand why)

But this is still not enough. If you want to print the number read from 0xcfc into eax with rep movsw, you need to first convert it into a string. Converting a number into a string in x86 assembly (either decimal or hexadecimal) is quite frequently asked in SO, so check some previous answers to get the idea:

Is this code correct (Number plus number, then print the result)

Note that you'll need as many bytes as there are characters in the number, or 2 x number of characters if you want to use rep movsw (see below).

Then in the code used to write to video memory, you seem to copy binary values to video memory without any conversion. So after doing the above 2 fixes, you would probably get some colored characters in the first 64 characters of the first row. See my recent answer to a SO question on printing a string without OS, it has example code with 2 different ways to do it.

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top