【发布时间】:2021-02-15 20:20:45
【问题描述】:
我有这段代码可以启用光标:
inline uint8_t inb(uint16_t port)
{
uint8_t ret;
asm volatile ( "inb %1, %0"
: "=a"(ret)
: "Nd"(port) );
return ret;
}
static inline void outb(uint16_t port, uint8_t val)
{
asm volatile ( "outb %0, %1" : : "a"(val), "d"(port) );
}
int main(void)
{
outb(0x3D4, 0x0A);
outb(0x3D5, (inb(0x3D5) & 0xC0) | 1);
outb(0x3D4, 0x0B);
outb(0x3D5, (inb(0x3D5) & 0xE0) | 2);
}
我不想使用内联汇编并在 nasm 汇编中编写它,但是当使用 outb 的汇编实现而不是内联汇编时,它不会正确启用光标。 nasm 函数的声明:
extern void outb(uint16_t port, uint8_t val);
以及功能:
outb:
mov dx, di
mov eax, esi
out dx, al
ret
有什么问题?
更新: 该函数现在看起来像这样,但它仍然不起作用:
outb:
push ebp
mov esp, ebp
mov dx, word [ebp+2]
mov al, byte [ebp+3]
out dx, al
mov esp, ebp
pop ebp
ret
【问题讨论】:
-
你对 c++ 中的 nasm 函数的声明是什么?问题可能在于参数如何传递给您的 asm 函数。
-
您应该将所有外部 asm 函数声明为 extern "C"。 c++ 中的参数传递可能会因 -O 优化参数或其他编译选项而异。这意味着 asm 函数的函数参数应该在堆栈上传递。
-
你为什么不想使用内联汇编?! GCC 可以优化内联汇编器,但肯定不能使用您的外部 nasm 函数。
-
偏移量
ebp+2和ebp+3是错误的。也许您正在计算双字而不是字节?给自己画一张堆栈布局图,记住每个参数都是作为一个 4 字节的 dword 推送的。你应该以mov dx, word [ebp+8]和mov al, byte [ebp+12]结尾。当然,首先没有必要使用ebp设置堆栈帧,因为您可以访问与esp相关的参数,如Antti 的回答。 -
第一个
mov esp, ebp也是倒数,应该是mov ebp, esp。
标签: c gcc x86 nasm inline-assembly