Page 1 of 1

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

Posted: Sat Oct 29, 2016 1:04 am
by 0CodErr
Returned value:
* eax = -1 - error (access to PCI is disabled or parameters
are not supported); otherwise
* al/ax/eax (depending on requested size) contains the data;
the other part of register eax is destroyed
А что, если data = -1? Это ведь будет не отличить от error.

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

Posted: Mon Oct 31, 2016 10:45 am
by art_zh
0CodErr
FFFFFFFF - это дефолтное состояние по стандарту PCI.
Так что если ты прочитал -1 из стандартного регистра, то он либо неинициализирован, либо обращение было направлено к пустому слоту.

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

Posted: Mon Oct 31, 2016 10:54 am
by 0CodErr
art_zh, спасибо, теперь понятно, почему так.

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

Posted: Mon Oct 31, 2016 10:47 pm
by 0CodErr
Я делаю обёртки для своей 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;
(* -------------------------------------------------------- *)

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

Posted: Mon Oct 31, 2016 11:03 pm
by Siemargl
Если паскаль сохраняет используемые регистры, то почти все ОК.
x86 calling convention - AX, CX, DX внутри функций свободно применимы, остальные надо сохранять.

Только не используй Byte в параметрах - только 32-битные параметры.

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

Posted: Mon Oct 31, 2016 11:31 pm
by 0CodErr
Только не используй 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 возвращает байт, что логично, потому что именно байт читали.

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

Posted: Tue Nov 01, 2016 12:08 am
by Siemargl
0CodErr wrote:Если было бы не Byte, а Dword, то программист мог бы по ошибке передать значение, выходящее за пределы диапазона Byte, а компилятор промолчал бы. Я считаю, что здесь использование Byte вполне оправдано.
Точно так же ReadPCIByte возвращает байт, что логично, потому что именно байт читали.
Проверь, что именно компилятор засовывает в стек. Нужно 32-битное значение (даже если данные там в младшем байте). Иначе будет невозможно нормально вызывать твои функции.

Ну и к интероперабельности - строки только asciiz, структуры (record) с явным выравниванием (или без), выделенная память передаваемая - только через сисфункции.

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

Posted: Thu Nov 03, 2016 4:54 pm
by 0CodErr
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, но и из любого другого, поддерживающего такое соглашение вызова(а его все поддерживают, насколько знаю).

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

Posted: Thu Nov 03, 2016 8:47 pm
by Siemargl
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]

А то в старших байтах будет мусор

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

Posted: Thu Nov 03, 2016 9:03 pm
by 0CodErr
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

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

Posted: Fri Nov 04, 2016 1:05 am
by Siemargl
прости, проблемы паскаля меня мало волнуют - ты приводишь примеры, которые разбирает компилятор

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

вот тебе несуществующая инструкция
http://x86.renejeschke.de/html/file_mod ... d_209.html

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

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

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

Posted: Sun Nov 06, 2016 2:02 am
by brunnel
0CodErr

Code: Select all

movzx eax, byte ptr [esp]
push eax

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

Posted: Mon Nov 07, 2016 5:08 pm
by 0CodErr
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. :)