`asm()` 函数在 C 语言中是如何工作的?
How does the `asm()` function works in C language?
我正在学习操作系统开发,当然是初学者。我想在实模式环境中构建我的系统,这是一个使用 C 语言的 16 位环境。
在 C 中,我使用函数 asm()
将代码转换为 16 位,如下所示:
asm(".code16")
用 GCC 语言生成 16 位可执行文件(虽然不完全是)。
问题:
假设我有两个头文件 head1.h
和 head2.h
以及一个 main.c
文件。 main.c
文件内容如下:
asm(".code16");
#include<head1.h>
#include<head2.h>
int main(){
return 0;
}
现在,由于我使用生成 16 位可执行文件的命令开始我的代码,然后包含 head1.h
和 head2.h
,我是否需要在所有头文件中执行相同的操作去创造? (或)添加行 asm(".code16");
一次就足够了吗?
OS: Ubuntu
编译器:Gnu CC
在head1.h
和head2.h
中都不需要添加asm("code16")
。
主要原因是 C pre-compiler 的工作原理。替换了main.c
.
中head1.h
和head2.h
的内容
请检查 How `#include' Works 了解更多信息。
希望对您有所帮助!
此致,
米格尔·安格尔
回答您的问题:asm
块出现在翻译单元的开头就足够了。
所以放在开头一次就可以了。
但您可以做得更好:您可以完全避免它并改用 the -m16
command line option (available from 5.2.0)。
但你可以做得更好:你可以完全避免它。
-m16
和.code16
的作用是使32位代码在实模式下可执行,不是产生实模式代码。
看
16.c
int main()
{
return 4;
}
提取原始 .text 片段
>gcc -c -m16 16.c
>objcopy -j .text -O binary 16.o 16.bin
>ndisasm 16.bin
我们得到
00000000 6655 push ebp
00000002 6689E5 mov ebp,esp
00000005 6683E4F0 and esp,byte -0x10
00000009 66E800000000 call dword 0xf
0000000F 66B804000000 mov eax,0x4
00000015 66C9 o32 leave
00000017 66C3 o32 ret
这只是填充了操作数大小前缀的 32 位代码。
On a real pre-386 machine this won't work as the 66h opcode is UD。
有旧的 16 位编译器,如 Turbo C1,可以正确解决 real-mode 应用程序的问题。
或者,尽快切换到保护模式或考虑使用 UEFI。
1 网上有。这个编译器和我一样大!
我正在学习操作系统开发,当然是初学者。我想在实模式环境中构建我的系统,这是一个使用 C 语言的 16 位环境。
在 C 中,我使用函数 asm()
将代码转换为 16 位,如下所示:
asm(".code16")
用 GCC 语言生成 16 位可执行文件(虽然不完全是)。
问题:
假设我有两个头文件 head1.h
和 head2.h
以及一个 main.c
文件。 main.c
文件内容如下:
asm(".code16");
#include<head1.h>
#include<head2.h>
int main(){
return 0;
}
现在,由于我使用生成 16 位可执行文件的命令开始我的代码,然后包含 head1.h
和 head2.h
,我是否需要在所有头文件中执行相同的操作去创造? (或)添加行 asm(".code16");
一次就足够了吗?
OS: Ubuntu
编译器:Gnu CC
在head1.h
和head2.h
中都不需要添加asm("code16")
。
主要原因是 C pre-compiler 的工作原理。替换了main.c
.
head1.h
和head2.h
的内容
请检查 How `#include' Works 了解更多信息。
希望对您有所帮助!
此致,
米格尔·安格尔
回答您的问题:asm
块出现在翻译单元的开头就足够了。
所以放在开头一次就可以了。
但您可以做得更好:您可以完全避免它并改用 the -m16
command line option (available from 5.2.0)。
但你可以做得更好:你可以完全避免它。
-m16
和.code16
的作用是使32位代码在实模式下可执行,不是产生实模式代码。
看
16.c
int main()
{
return 4;
}
提取原始 .text 片段
>gcc -c -m16 16.c
>objcopy -j .text -O binary 16.o 16.bin
>ndisasm 16.bin
我们得到
00000000 6655 push ebp
00000002 6689E5 mov ebp,esp
00000005 6683E4F0 and esp,byte -0x10
00000009 66E800000000 call dword 0xf
0000000F 66B804000000 mov eax,0x4
00000015 66C9 o32 leave
00000017 66C3 o32 ret
这只是填充了操作数大小前缀的 32 位代码。
On a real pre-386 machine this won't work as the 66h opcode is UD。
有旧的 16 位编译器,如 Turbo C1,可以正确解决 real-mode 应用程序的问题。
或者,尽快切换到保护模式或考虑使用 UEFI。
1 网上有。这个编译器和我一样大!