Проверка устройств PCI на ассемблере

У меня есть простая программа, которая должна читать PCI configuration space (только для первого устройства PCI). Но это не работает. ЯСМ:

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 в качестве ассемблера.


person Vanzef    schedule 22.03.2013    source источник


Ответы (1)


Вы не можете использовать out или in с 16-битными непосредственными номерами портов. Для in и out.

Поэтому вам нужно сохранить номер порта в 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, ровно 4 байта) значением, которое вы читаете в eax из порта 0xcf8 (если вы сначала исправили непосредственные 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, поэтому проверьте некоторые предыдущие ответы, чтобы получить представление:

Правилен ли этот код (число плюс число, затем распечатать результат)

Обратите внимание, что вам понадобится столько байтов, сколько символов содержится в числе, или удвоенное количество символов, если вы хотите использовать rep movsw (см. ниже).

Затем в коде, используемом для записи в видеопамять, вы, кажется, копируете двоичные значения в видеопамять без какого-либо преобразования. Таким образом, после выполнения двух указанных выше исправлений вы, вероятно, получите несколько цветных символов в первых 64 символах первой строки. См. мой недавний ответ на вопрос SO о печати строки без ОС , у него есть пример кода с двумя разными способами сделать это.

Надеюсь это поможет.

person nrz    schedule 22.03.2013
comment
Спасибо. Но программа ничего не делает (например, очищает экран). Это необходимо для всех операций in/out или только для 32-битных (например, eax и т. д.)? - person Vanzef; 22.03.2013
comment
@Vanzef Добавлено объяснение дополнительных проблем в вашем коде. in и out разрешить только 8-битные непосредственные адреса портов, и то же самое для al, ax и eax. Для 16-битного порта необходимо использовать адрес dx. - person nrz; 22.03.2013
comment
...и ты не хочешь bits 32! - person Frank Kotler; 22.03.2013