`asm()`函数如何在C语言中工作?

时间:2017-02-12 17:30:19

标签: gcc assembly operating-system kernel bootloader

我正在学习操作系统开发和课程初学者。我想在实模式环境中构建我的系统,这是一个使用C语言的16位环境。

在C中,我使用函数asm()将代码转换为16位,如下所示:

asm(".code16")

以GCC的语言生成16位可执行文件(不完全如此)。

问题:

假设我有两个头文件head1.hhead2.h以及一个main.c文件。 main.c文件的内容如下:

asm(".code16");
#include<head1.h>
#include<head2.h>
int main(){
  return 0;
}

现在,由于我使用生成16位可执行文件的命令启动了我的代码,然后包含head1.hhead2.h,我是否需要在我要创建的所有头文件中执行相同操作? (或)一次添加行asm(".code16");是否足够?

操作系统:Ubuntu

编译器:Gnu CC

2 个答案:

答案 0 :(得分:5)

回答您的问题: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 C 1 ,可以正确解决实模式应用程序的问题。

Turbo C code generation options

或者,尽快切换到保护模式或考虑使用UEFI。

1 可在线获取。这个编译器和我一样老了!

答案 1 :(得分:0)

不需要在asm("code16")head1.h中添加head2.h

主要原因是C预编译器的工作原理。它取代了head1.hhead2.hmain.c的内容。

请查看How `#include' Works以获取更多信息。

希望它有所帮助!

致以最诚挚的问候,

MiguelÁngel