SysFn62.4(|5|6):ReadPCIByte(|Word|Dword)

Applications development, KoOS API questions
  • 0CodErr
    FFFFFFFF - это дефолтное состояние по стандарту PCI.
    Так что если ты прочитал -1 из стандартного регистра, то он либо неинициализирован, либо обращение было направлено к пустому слоту.
    Евангелие от Иоанна: стих 1

    Code: Select all

    ; В начале было Слово:
    B32:        mov     ax, os_stack       ; Selector for os
    [/size]
  • art_zh, спасибо, теперь понятно, почему так.
  • Я делаю обёртки для своей KolibriOS библиотеки.

    Всё правильно, надеюсь?
    Spoiler:

    Code: Select all

    (* -------------------------------------------------------- *)
    {62.0}    Function  GetPCIVersion: Dword; StdCall;
              Asm
                      push   ebx
                      mov    eax, 62
                      mov    bl, 0
                      int    64
                      pop    ebx
              End;
    (* -------------------------------------------------------- *)
    {62.1}    Function  GetLastPCIBus: Dword; StdCall;
              Asm
                      push   ebx
                      mov    eax, 62
                      mov    bl, 1
                      int    64
                      pop    ebx
              End;
    (* -------------------------------------------------------- *)
    {62.2}    Function  GetPCIAddressingMode: Dword; StdCall;
              Asm
                      push   ebx
                      mov    eax, 62
                      mov    bl, 2
                      int    64
                      pop    ebx
              End;
    (* -------------------------------------------------------- *)
    {62.3}    {UNDEFINED}
    (* -------------------------------------------------------- *)
    {62.4}    Function  ReadPCIByte(Bus, Device, Func, Reg: Byte): Byte; StdCall;
              Asm
                      push   ebx
                      mov    eax, 62
                      mov    bl, 4
                      mov    bh, Bus
                      mov    cl, Reg
                      mov    ch, Device
                      shl    ch, 3
                      or     ch, Func
                      int    64
                      pop    ebx
              End;
    (* -------------------------------------------------------- *)
    {62.5}    Function  ReadPCIWord(Bus, Device, Func, Reg: Byte): Word; StdCall;
              Asm
                      push   ebx
                      mov    eax, 62
                      mov    bl, 5
                      mov    bh, Bus
                      mov    cl, Reg
                      mov    ch, Device
                      shl    ch, 3
                      or     ch, Func
                      int    64
                      pop    ebx
              End;
    (* -------------------------------------------------------- *)
    {62.6}    Function  ReadPCIDword(Bus, Device, Func, Reg: Byte): Dword; StdCall;
              Asm
                      push   ebx
                      mov    eax, 62
                      mov    bl, 6
                      mov    bh, Bus
                      mov    cl, Reg
                      mov    ch, Device
                      shl    ch, 3
                      or     ch, Func
                      int    64
                      pop    ebx
              End;
    (* -------------------------------------------------------- *)
    {62.7}    {UNDEFINED}
    (* -------------------------------------------------------- *)
    {62.8}    Function  WritePCIByte(Bus, Device, Func, Reg: Byte; Data: Byte): Dword; StdCall;
              Asm
                      push   ebx
                      mov    eax, 62
                      mov    bl, 8
                      mov    bh, Bus
                      mov    cl, Reg
                      mov    ch, Device
                      shl    ch, 3
                      or     ch, Func
                      mov    dl, Data
                      int    64
                      pop    ebx
              End;
    (* -------------------------------------------------------- *)
    {62.9}    Function  WritePCIWord(Bus, Device, Func, Reg: Byte; Data: Word): Dword; StdCall;
              Asm
                      push   ebx
                      mov    eax, 62
                      mov    bl, 9
                      mov    bh, Bus
                      mov    cl, Reg
                      mov    ch, Device
                      shl    ch, 3
                      or     ch, Func
                      mov    dx, Data
                      int    64
                      pop    ebx
              End;
    (* -------------------------------------------------------- *)
    {62.10}   Function  WritePCIDword(Bus, Device, Func, Reg: Byte; Data: Dword): Dword; StdCall;
              Asm
                      push   ebx
                      mov    eax, 62
                      mov    bl, 10
                      mov    bh, Bus
                      mov    cl, Reg
                      mov    ch, Device
                      shl    ch, 3
                      or     ch, Func
                      mov    edx, Data
                      int    64
                      pop    ebx
              End;
    (* -------------------------------------------------------- *)
  • Если паскаль сохраняет используемые регистры, то почти все ОК.
    x86 calling convention - AX, CX, DX внутри функций свободно применимы, остальные надо сохранять.

    Только не используй Byte в параметрах - только 32-битные параметры.
  • Только не используй Byte в параметрах - только 32-битные параметры.
    Siemargl, я по возможности придерживаюсь этого. Но иногда из-за этого пришлось бы делать дополнительные преобразования. С другой стороны, сам вызов int 64 гораздо медленнее.
    Если паскаль сохраняет используемые регистры, то почти все ОК.
    x86 calling convention - AX, CX, DX внутри функций свободно применимы, остальные надо сохранять.
    Ну я согласно документации делаю:
    Register saving conventions

    Procedures and functions must preserve the EBX, ESI, EDI, and EBP registers, but can modify the EAX, EDX, and ECX registers. When implementing a constructor or destructor in assembler, be sure to preserve the DL register. Procedures and functions are invoked with the assumption that the CPU's direction flag is cleared (corresponding to a CLD instruction) and must return with the direction flag cleared.
    Или вот пример
    Spoiler:

    Code: Select all

    {20.2}    Function  OutputMidi(Data: Byte): Integer; StdCall;
              Asm
                      push   ebx
                      mov    eax, 20
                      mov    ebx, 2
                      mov    cl, Data
                      int    64
                      pop    ebx
              End;
    Если было бы не Byte, а Dword, то программист мог бы по ошибке передать значение, выходящее за пределы диапазона Byte, а компилятор промолчал бы. Я считаю, что здесь использование Byte вполне оправдано.
    Точно так же ReadPCIByte возвращает байт, что логично, потому что именно байт читали.
  • 0CodErr wrote:Если было бы не Byte, а Dword, то программист мог бы по ошибке передать значение, выходящее за пределы диапазона Byte, а компилятор промолчал бы. Я считаю, что здесь использование Byte вполне оправдано.
    Точно так же ReadPCIByte возвращает байт, что логично, потому что именно байт читали.
    Проверь, что именно компилятор засовывает в стек. Нужно 32-битное значение (даже если данные там в младшем байте). Иначе будет невозможно нормально вызывать твои функции.

    Ну и к интероперабельности - строки только asciiz, структуры (record) с явным выравниванием (или без), выделенная память передаваемая - только через сисфункции.
  • Siemargl, у меня из 260-ти функций только в 50-ти используется Byte, а в остальных Dword\Pointer.
    Я проверил, что делает компилятор, перед вызовом функции он делает примерно так

    Code: Select all

      00000022: 8A 04 24           mov         al,byte ptr [esp]
      00000025: 50                 push        eax
    То есть, на стеке всё равно будет Dword.
    Ну и к интероперабельности - строки только asciiz, структуры (record) с явным выравниванием (или без), выделенная память передаваемая - только через сисфункции.
    Это уже всё согласно документации к системным функциям KolibriOS.
    Ну и, естественно, что, поскольку функции StdCall, то и использоваться могут не только из Delphi\FreePascal, но и из любого другого, поддерживающего такое соглашение вызова(а его все поддерживают, насколько знаю).
  • 0CodErr wrote:Siemargl, у меня из 260-ти функций только в 50-ти используется Byte, а в остальных Dword\Pointer.
    Я проверил, что делает компилятор, перед вызовом функции он делает примерно так

    Code: Select all

      00000022: 8A 04 24           mov         al,byte ptr [esp]
      00000025: 50                 push        eax
    То есть, на стеке всё равно будет Dword.
    Хорошо, но желательно чтобы он делал
    movzx al,byte ptr [esp]

    А то в старших байтах будет мусор
  • Siemargl wrote:Хорошо, но желательно чтобы он делал
    movzx al,byte ptr [esp]
    Не-не, тут ты не прав, нет такой команды просто.
    Если ты имел в виду movzx eax, то я думаю, что компилятор наверняка следит за использованием регистров.
    А то в старших байтах будет мусор
    Ну и что с того?
    Например, вызываем

    Code: Select all

    Var MyByte: Byte;
    MyByte := ReadPCIByte(Bus, Device, Func, Reg);
    А сама функция ReadPCIByte, как видно в посте выше, не использует никаких старших байтов. А если бы использовала, то следовало объявить параметры не Byte, а Dword, например. Ну и тогда, соответственно, компилятор клал бы на стек значение eax целиком. Проще говоря, компилятор ведёт себя вполне логичным образом.

    Более того, под номер функции устройства отводится всего 3 бита.
    Так что, можно даже не байт использовать, а определить

    Code: Select all

    Type   TThreeBits = 0..7;
    далее, меняем тип параметра в функции ReadPCIByte

    Code: Select all

    Func: TThreeBits 
    И теперь, если передать, например, значение Func, равное 10, то получим
    Constant expression violates subrange bounds
  • прости, проблемы паскаля меня мало волнуют - ты приводишь примеры, которые разбирает компилятор

    а я про более низкоуровневый код

    вот тебе несуществующая инструкция
    http://x86.renejeschke.de/html/file_mod ... d_209.html
  • Siemargl wrote:вот тебе несуществующая инструкция
    http://x86.renejeschke.de/html/file_mod ... d_209.html
    Не знаю уж, что я там должен был найти, может и плохо искал, конечно. Но вот тебе из мануала
    Spoiler:
    1.PNG
    1.PNG (64.87 KiB)
    Viewed 8851 times
    И никаких MOVZX reg8, reg/mem8 там и близко нет.
  • 0CodErr

    Code: Select all

    movzx eax, byte ptr [esp]
    push eax