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

Pan*_*der 1 assembly gcc operating-system kernel bootloader

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

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

asm(".code16")
Run Code Online (Sandbox Code Playgroud)

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

题:

假设我有两个头文件head1.hhead2.hmain.c文件.main.c文件内容如下:

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

现在,自从我开始我的代码的命令生成16位可执行文件,然后包括head1.hhead2.h,我需要做的,我创建的所有头文件一样吗?(或)添加asm(".code16");一次是否足够?

操作系统:Ubuntu

编译器:Gnu CC

Mar*_*oom 5

回答你的问题:asm块足以出现在翻译单元的开头.
所以在开头就把它放一次就行了.

但是你可以做的更好:你可以完全避免它,使用-m16命令行选项(可从5.2.0)代替.

但你可以做得更好:你可以完全避免它.


的效果-m16.code16是使32位代码可执行在实模式下,这是产生实模式的代码.

16.C

int main()
{
   return 4;
}
Run Code Online (Sandbox Code Playgroud)

提取原始.text

>gcc -c -m16 16.c
>objcopy -j .text -O binary 16.o 16.bin
>ndisasm 16.bin
Run Code Online (Sandbox Code Playgroud)

我们得到

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
Run Code Online (Sandbox Code Playgroud)

这只是填充了操作数大小前缀的32位代码.
在真正的386前机器上,由于66h操作码是UD,因此无法工作.


有一些旧的16位编译器,如Turbo C 1,可以正确解决实模式应用程序的问题.

Turbo C代码生成选项

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


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