好的,我需要对PCI BIOS服务目录(32位模式)执行CALL FAR以验证PCI BIOS是否存在。
注意:我正在开发一个简单的磁盘驱动程序,用于我们正在开发一所大学的简单操作系统。我知道这是非常具体的,但我将从内核代码中完成所有这些。
假设我已找到相关地址。执行远程调用给定地址的正确汇编语言是什么?有人可以发布一些远程调用给定32位地址的汇编代码吗?到目前为止我看到的例子的语法令人困惑。
谢谢!
编辑:在我的具体情况下,我已经找到了PCI BIOS服务目录,它给了我物理地址(32位)。鉴于这个32位地址,我需要什么类型的远程调用?例如,我在英特尔手册中读到,远程调用可以改变任务,什么不可以。我怎么知道我要做什么来远远调用这个PCI BIOS服务目录的物理地址?
更新:
以下是我发现的一些令我困惑的代码(内联):
asm("lcall (%%edi)"
: "=a" (return_code),
"=b" (address),
"=c" (length),
"=d" (entry)
: "0" (service),
"1" (0),
"D" (&bios32_indirect));
我在此源文件中找到了:http://www.pell.portland.or.us/~orc/Code/Archive/linux-1.2.13/arch/i386/kernel/bios32.c
我认为我想要做的是在实际装配中相当于上面的内联。
答案 0 :(得分:2)
从手册:
to make a asm call use the below format
asm( command1 %0
command2
:output registers with there mapping to variable
:input registers with mapping.
);
example
asm ("movl %1, %%ebx;"
"movl %%ebx, %0;"
: "=r" ( val )
: "r" ( no )
: "%ebx" // clobbered register
);
here %1 is input variable %0 is output.
要创建lcall
您需要的段和实际的32位地址:
bios32_indirect.address = directoy_address;
uint32 kernelcodesegment = 0;
asm ("movl %%cs, %0;"
: "=r" (kernelcodesegment)
:);
bios32_indirect.segment = kernelcodesegment;
答案 1 :(得分:1)
如果存储器是平坦的,即CS的基数为0并覆盖整个32位地址空间
call <address>
其中address是32位目标地址。
编辑:啊,我看到你有一个实际地址。我假设这是在Linux上运行的设备驱动程序。我对linux内核没有任何经验,但我认为这个物理地址没有按1:1映射到虚拟地址。您需要将其映射到虚拟地址(抱歉,不知道如何在Linux中),然后调用该虚拟地址。但这提出了一个问题,即您需要什么样的PCI BIOS功能,直接进入操作系统外的BIOS通常是错误的方法。
答案 2 :(得分:0)
如果您提到您正在处理的操作系统,那肯定会有所帮助。 让我们说它是Windows 32Bit然后假设您确定知道物理地址,您仍然需要获得与之相关的PTE。您不能只是拨打该特定地址,因为您处于保护模式,而您拥有的地址是虚拟地址。您可以将物理映射到虚拟,但它很复杂。
如果你想知道你是否可以查看该地址的内容,请使用WinDBG并执行:
!dd <address>
这将在您指定的物理地址处显示DWORD。 当您知道该做什么时,从物理到虚拟的翻译很简单(看着CR3赢了,不会帮助您:)
现在,如果你正在使用不同的操作系统,这是一个不同的故事,因为PTE的映射方式不同。
另外,如前所述,你不能只调用bios,因为它实际上是16位而不是32位。 在保护模式下(在i386中,可能在之后),有一种特定的技术可以使用vx86或其他类似的东西,但我忘记了确切的术语。虽然可行但成本很高,因为它涉及任务切换和其他各种事情。
如果您需要开发磁盘驱动程序,那么组中的硬件人员应该能够为您提供可用的端口,以便您可以对设备进行IO调用,从而无需访问BIOS。 / p>