02-1【编写loader工程内容】利用内联汇编显示字符串


在开发操作系统过程中,有时必须使用某些特殊的指令(如inb/outb/hlt),而C编译器无法自动使用这些指令。
因此,如果要使用这些指令,有两种方式:

  • 1.在汇编文件中为该指令的使用创建汇编函数(子程序),然后在C代码中以函数调用的方式去使用;

  • 2.使用内联汇编:即在C代码中嵌入汇编程序

在大多数情况下,使用内联汇编会更加简单、易用。因此,这里用GCC内联汇编的写法。


内联汇编格式参考链接:https://www.cnblogs.com/shuijiaoa/p/16060156.html


一些说明


(1)const 关键字

关键字const用来定义常量,如果一个变量被const修饰,那么它的值就不能再被改变.

与预编译指令相比,const修饰符有以下的优点:

1、预编译指令只是对值进行简单的替换,不能进行类型检查

2、可以保护被修饰的东西,防止意外修改,增强程序的健壮性

3、编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

参考链接:https://blog.csdn.net/xingjiarong/article/details/47282255


(2)函数参数为常量的好处

函数的参数,‌如果定义为常量,
‌意味着在函数内部对该参数的任何尝试修改都应该被禁止,‌以保持其值的稳定性。
‌这种设计有助于确保函数的行为可预测,‌避免因参数值变化导致的意外结果。


(3)函数参数为常量时,调用函数仍然能改变参数值

C语言的“常量”指的是字面值常量,例如const int a = 10;中的10。而a称为常变量,它本质上是一个不能改变的变量。
这种不能改变的特性是语法层面的编译器通过语法检查来确保a没有在代码中被修改过。
在运行时没有任何机制确保a不被修改,它就和任何普通变量一样

链接:https://www.zhihu.com/question/372226898/answer/1018899469


(4)在C语言中\n 和 \r 区别

  • \n:‌代表换行符(‌newline)‌,‌其主要作用是将光标移动到下一行的开头。‌在C语言编程中,‌\n用于输出文本时,‌会在当前位置插入一个换行符,‌使得接下来的文本从下一行的开头开始输出。‌

  • \r:‌代表回车符(‌carriage return)‌,‌其主要作用是将光标移动到当前行的开头。‌在C语言中,‌\r用于输出文本时,‌会在当前位置插入一个回车符,‌使得光标回到当前行的开头,‌而不是换行。‌




实操(编写loader_entry函数中的显示字符串的功能)


loader_16.c

__asm__(".code16gcc");

//显示字符串的函数
static void show_msg(const char * msg){
    //循环的读取字符
    char c;
    while( (c = *msg++) != '\0' ){  //*(解引用运算符)的优先级比 ++(自增运算符)的优先级高
        	asm(
                "mov $0xe , %%ah\n\t" //寄存器要加两个%符号
                "mov %[ch] , %%al\n\t"
                "int $0x10"::[ch]"r"(c)  //r代表任意寄存器,把ch字符存入任意寄存器中,并将c映射到该寄存器中
            );	          
    } 
}

void loader_entry(void){
    show_msg("....loading....\n\r"); 
    for(;;){} 
} 


编译运行调试后:


为了避免编译器优化代码,可以加上volatile关键字:








posted @ 2024-07-23 17:03  卡卡发  阅读(40)  评论(0)    收藏  举报