资讯详情

学堂在线_操作系统_notes_第4讲_Lab1_bootloader启动ucore os_C函数调用的实现+GCC内联汇编INLINE ASSEMBLY...

学堂在线_操作系统_notes_第4讲_Lab1_bootloader启动ucore os_C实现函数调用 GCC内联汇编INLINE ASSEMBLY X86中断处理

  • C实现函数调用
    • 参考资料
  • GCC内联汇编INLINE ASSEMBLY
    • 什么是内联汇编(Inline assembly )?
    • 有何用处?
    • 如何工作?
    • Example 1
    • Syntax
    • Example 2
    • Example 3
    • 参考资料
  • X86中断处理
    • 了解x86中的中断源
    • 了解CPU如何处理与操作系统的中断
    • 中断向量表(中断描述符表)IDT)进行初始化


20220629.No.1824


C实现函数调用

  • 了解C函数调用是如何在汇编级实现的

  • 了解如何在汇编级代码中调用C函数

  • 理解基于EBP寄存器函数调用栈

  • 其他需要注意的事项

    • 参数(parameters)& 函数返回值(return values)可通过寄存器堆栈位于内存中来传递。用寄存器效率更高。

    • 不需要保存/恢复(save/restore)寄存器.

参考资料

  • Understanding the Stack: http://www.cs.umd.edu/class/sum2003/cmsc311/Notes/Mips/stack.html

GCC内联汇编INLINE ASSEMBLY

什么是内联汇编?(Inline assembly )?

  • 这是GCC扩展C语言
  • 汇编指令可以直接插入C语句

有何用处?

  • 调用C语言不支持的指令(如用C语言不能表示寄存器)
  • C语言手动优化汇编

如何工作?

  • 汇编指令用给定的模板和约束生成
  • 汇编源代码在C函数中形成.

Example 1

// 汇编语言: Assembly (*.S):  movl $0xffff, %eax // 把 0xffff值 赋给 eax寄存器。  // 以上代码 改写为 C内联汇编: Inline assembly (*.c):  asm ("movl $0xffff, %?x\n") // 把 0xffff值 赋给 eax寄存器。asm 是 内联汇编的关键词。 

Syntax

// 内联汇编代码的完整句法: asm ( "assembler template" // asm 是 内联汇编的关键词。assembler template处 用于填入形,如用于填入形movl $0xffff, %?x\n字符串。  : output operands // (optional) 输出操作数的约束表示。用寄存器表示变量。  : input operands // (optional) 用寄存器表示输入操作数的约束。  : clobbers // (optional) 约束表示。用寄存器表示变量。  ); 

Example 2

Inline assembly (*.c):  uint32_t cr0; // cr0 是 内存变量。  asm volatile ("movl %%cr0, %0\n" :"=r"(cr0)); // 把 cr0寄存器的值 写入 %0寄存器,(存器 然后表示输出操作数的约束) 寄存器值%0 赋给cr0内存变量。
	cr0|= 0x80000000; // 把 cr0内存变量的某个bit 置为 1.
	asm volatile ("movl %0, %%cr0\n" ::"r"(cr0)); // 把 cr0内存变量的值 写入 %0寄存器,(用 输入操作数的约束表示)再把 %0寄存器的值 赋给 cr0寄存器。

// •volatile (不需要做进一步优化,不需要重新排序):No reordering; No elimination
// •%0 (%0寄存器):The first constraint following
// •r (任一寄存器):A constraint; GCC is free to use any register

// 把上述内联汇编代码 翻译为 汇编语言:
Generated asssembly code (*.s):
	movl %cr0, %ebx // 把 cr0寄存器的值 赋给 ebx寄存器。
	movl %ebx, 12(%esp) // 把 ebx寄存器的值 赋给 esp局部变量。
	orl $-2147483648, 12(%esp) // 把 esp局部变量的某个bit 置为 1.
	movl 12(%esp), %eax // 把 esp局部变量的值 赋给 eax寄存器。
	movl %eax, %cr0 // 把 eax寄存器的值 赋给 cr0寄存器。

// 内联汇编的代码更简洁,因为加入约束表示后,由gcc编译器自动把寄存器之间的关系建立好了。

Example 3

// 调用 "int 80"指令 产生 软中断,内联汇编代码如下:
long __res, arg1 = 2, arg2 = 22, arg3 = 222, arg4 = 233; // 给 相应局部变量 赋值。
__asm__ volatile ("int $0x80" // 软中断指令。
	: "=a" (__res) // 输出操作数的约束表示:eax寄存器 表示 返回值。
	: "0" (11),"b" (arg1),"c" (arg2),"d" (arg3),"S" (arg4)); // 输入操作数的约束表示:把 arg1局部变量的值 赋给 ebx寄存器,把 arg2局部变量的值 赋给 ecx寄存器,把 arg3局部变量的值 赋给 edx寄存器,把 arg4局部变量的值 赋给 esi寄存器。

// Constraints (字母与寄存器之间的对应关系(约定、约束表示)):
// a = %eax
// b = %ebx
// c = %ecx
// d = %edx
// S = %esi
// D = %edi
// 0 = same as the first

// 上述 内联汇编代码 翻译为 汇编语言:
// 把 相应局部变量的值 赋给 相应寄存器,再调用 "int 80"指令 产生 软中断,最后把 eax寄存器的值 作为 返回值 返回。
……
movl $11, %eax
movl -28(%ebp), %ebx
movl -24(%ebp), %ecx
movl -20(%ebp), %edx
movl -16(%ebp), %esi
int $0x80
movl %eax, -12(%ebp)

参考资料

  • GCC Manual 6.41 –6.43
  • Inline assembly for x86 in Linux: http://www.ibm.com/developerworks/library/l-ia/index.html

X86中的中断处理

  • 详见PPT。

了解x86中的中断源

了解CPU与操作系统如何处理中断

能够对中断向量表(中断描述符表,简称IDT)进行初始化

标签: 二极管cmsc

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台