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 8717 times
    И никаких MOVZX reg8, reg/mem8 там и близко нет.
  • 0CodErr

    Code: Select all

    movzx eax, byte ptr [esp]
    push eax
  • brunnel, yes, i noticed Siemargl about it in the post above.
    Если ты имел в виду movzx eax, то я думаю, что компилятор наверняка следит за использованием регистров.
    But it seems that Siemargl think that the compiler was made by stupid people who can not in the basic things.

    Also, movzx eax, byte ptr [esp] - It is not necessary. Because ReadPCIByte function does not use the high bytes of eax. So the compiler is right. :)
  • Who is online

    Users browsing this forum: No registered users and 4 guests