云班课学习内容

一、C语言中嵌入汇编代码

1、内嵌汇编语法

(1)C语言中嵌入汇编代码的写法:

asm(

汇编语句模板:

输出部分:

输入部分:

破坏描述部分);

说明:输出部分和输入部分对应着C语言中的函数调用时的参数(return也是一个输出部分)

例:

printf("val1:%d,val2:%d,val3:%d\n",val1,val2,val3);
asm volatile(
/*asm是GCC关键字asm的宏定义,表示内嵌汇编语句,与__sam__同,volatile是GCC关键字volatile的宏定义,告诉编译器不要对代码进行优化,与__volatile同*//
"movl $0,%%eax\n\t" /*clear %eax to 0,两个%中第一个用于转义*/
"addl %1,%%eax\n\t" /*%eax+=val1,是输入输出中的第二个数*/
"addl %2,%%eax\n\t" /*%eax+=val2,是输入输出中的第三个数*/
"movl %%eax,%0\n\t" /*val3=%eax*/
:"=m"(val3) /*output=m,只写,m表示写入内存
:"c"(val1),"d"(val2) /*input c:ecx d:edx*/
);
printf("val1:%d+val2:%d=val3:%d\n",val1,val2,val3); return 0;

(2)内嵌汇编常用限定符

限定符 描述
“a” 将输入变量放入eax
“b” 将输入变量放入ebx
“c” 将输入变量放入ecx
“d” 将输入变量放入edx
“s” 将输入变量放入esi
“D” 将输入变量放入edi
“q” 将输入变量放入eax,ebx,ecx,edx中的一个
“r” 将输入变量放入通用寄存器,也就是eax,ebx,ecx,edx,esi,edi中的一个
“A” 放入eax和edx,吧、把eax和edx合成一个64位的寄存器
“m” 内存变量
“o” 操作数为内存变量,但是其寻址方式是偏移量类型
“V” 操作数为内存变量,但寻址方式不是偏移量类型
“.” 操作数为内存变量,但寻址方式是自动增量
“p” 操作数是一个合法的内存地址(指针)
“g” 将输入变量放入eax,ebx,ecx,edx中的一个或者作为内存变量
“X” 操作数可以是任何类型
“I” 0-31之间的立即数(用于32位移位指令)
“J” 0-63之间的立即数(用于64位移位指令)
“N” 0-255之间的立即数(用于out指令)
“i” 立即数
“n” 立即数,有些系统不支持数字以外的立即数,这些系统应该使用n
“=” 操作数在指令中是只写的(输出操作数)
“+” 操作数在指令中是读写类型的(输入输出操作数)
“%” 该操作数可以和下一个操作数交换位置

二、三个法宝:存储程序计算机、函数调用堆栈、中断

1、计算机是如何工作的?(总结)--三个法宝

(1)存储程序计算机:所有计算机基础性的逻辑框架。

(2)函数调用堆栈:计算机中非常基础性的东西。最早的计算机没有高级语言,只有机器语言和汇编语言时没有函数的概念。而高级语言中有函数的概念,需要堆栈机制,是高级语言可以运行的基础。

堆栈是C语言程序运行时必须的一个记录调用路径和参数的空间。

--函数调用框架

--传递参数

--保存返回地址(保存返回值,如eax)

--提供局部变量空间

--等等

C语言编译器对堆栈的使用有一套规则,同一段C语言程序在不同的操作系统中产生的汇编代码可能会有一些差异。

了解堆栈存在的目的和编译器对堆栈使用的规则是理解操作系统一些关键性代码的基础。

(3)中断:计算机帮程序员做的一些工作。

中断

早期计算机没有中断时,需要执行完一个程序之后再执行另一个程序。

有了中断,就有了多道程序设计,即在系统中同时跑多道程序。

当中断发生时,CPU会把当前的eip,esp,ebp都压到一个内核堆栈中。CPU和内核代码共同实现了保存和回复现场。

2、利用mykernel实验模拟计算机硬件平台。

(1)搭建一个虚拟平台

(2)使用Linux源代码把CPU的配置配置好

(3)执行

cd LinuxKernel/Linux-3.9.4
qeum -kernel arch/x86/boot/bzImage /*加载内核*/

实验中遇到问题



①编译Linux内核出现include/linux/compiler-gcc.h:103:30: fatal error: linux/compiler-gcc5.h: No such file or directory

解决方案





解决方案:将用户转换为root即可

编译中:



完成:

qemu -kernel arch/x86/boot/bzImage



在mykernel目录中:



cd mykernel

输入ls命令会发现,该文件夹中含有mymain.c和myinterrupt.c两个文件。

/*mymain.c中开始启动操作系统,入口*/
void __init_my_start_kernel(void)
{
int i = 0;
while(1)
{
i++;
if(i%100000 == 0)
printk(KERN_NOTICE "my_start_kernel here %d \n",i);/*每循环十万次,打印一条消息*/
}

void my_timer_handler(void)/*myinterrupt.c中,时钟中断处理入口*/
{
printk(KERN_NOTICE "\N>>>>>>>>>>>>>>>>>>>>>my_timer_handler here <<<<<<<<<<<\n\n");
}

当按照课本敲完代码只有,出现了很多错误,都是因为敲代码的时候不认真,多了字母、少了字母或者是代码敲错。其中值得一提的一个错误是在mymain.c文件中的初始化函数,init前面是两个下划线,而不是一个。

之后运行成功:

三、深入理解函数调用堆栈

1、(1)esp:堆栈指针

(2)ebp:基址指针

(3)堆栈操作:①push栈顶地址减少4个字节(32位)

②pop栈顶地址增加4个字节(32位)

(4)ebp在C语言中用作记录当前函数调用基址

(5)其他关键寄存器

cs:eip总是指向下一条的指令地址

顺序执行:总是指向地址连续的下一条指令

跳转/分支:执行这样的指令的时候,cs:eip的值会根据程序需要被修改

call:将当前cs:eip的值压入栈顶,cd:eip指向被调用函数的入口地址

ret:从栈顶弹出原来保存在这里的cs:eip的值,放入cs:eip中

(6)建立被调用者函数的堆栈框架

pushl %ebp
movl %esp,%ebp
/*被调用者函数体*/
/*拆除被调用者函数的堆栈框架*/
movl %ebp,%esp
popl %ebp
ret

2、堆栈调用

(1)首先使用gcc -g生成test.c的debug版本的可执行文件test,然后使用objdump -S 获得test的反汇编文件。

    objdump -S test > test.txt



注意为什么在反汇编代码中,是用变址寻址,而不是直接用x或者y?

是因为:参数已经放在了堆栈中,只需要根据地址寻找即可。

2019-2020-1 20199302《Linux内核原理与分析》第三周作业的更多相关文章

  1. 2019-2020-1 20199329《Linux内核原理与分析》第九周作业

    <Linux内核原理与分析>第九周作业 一.本周内容概述: 阐释linux操作系统的整体构架 理解linux系统的一般执行过程和进程调度的时机 理解linux系统的中断和进程上下文切换 二 ...

  2. 2019-2020-1 20199329《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 一.上周问题总结: 未能及时整理笔记 Linux还需要多用 markdown格式不熟练 发布博客时间超过规定期限 二.本周学习内容: <庖丁解 ...

  3. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  4. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

  5. 2018-2019-1 20189221 《Linux内核原理与分析》第九周作业

    2018-2019-1 20189221 <Linux内核原理与分析>第九周作业 实验八 理理解进程调度时机跟踪分析进程调度与进程切换的过程 进程调度 进度调度时机: 1.中断处理过程(包 ...

  6. 2017-2018-1 20179215《Linux内核原理与分析》第二周作业

    20179215<Linux内核原理与分析>第二周作业 这一周主要了解了计算机是如何工作的,包括现在存储程序计算机的工作模型.X86汇编指令包括几种内存地址的寻址方式和push.pop.c ...

  7. 2019-2020-1 20209313《Linux内核原理与分析》第二周作业

    2019-2020-1 20209313<Linux内核原理与分析>第二周作业 零.总结 阐明自己对"计算机是如何工作的"理解. 一.myod 步骤 复习c文件处理内容 ...

  8. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  9. 《Linux内核原理与分析》第一周作业 20189210

    实验一 Linux系统简介 这一节主要学习了Linux的历史,Linux有关的重要人物以及学习Linux的方法,Linux和Windows的区别.其中学到了LInux中的应用程序大都为开源自由的软件, ...

  10. 2018-2019-1 20189221《Linux内核原理与分析》第二周作业

    读书报告 <庖丁解牛Linux内核分析> 第 1 章 计算工作原理 1.1 存储程序计算机工作模型 1.2 x86-32汇编基础 1.3汇编一个简单的C语言程序并分析其汇编指令执行过程 因 ...

随机推荐

  1. 用python写一个简单的文件上传

    用Pycharm创建一个django项目.目录如下: <!DOCTYPE html> <html lang="en"> <head> <m ...

  2. JQuery 总结篇

    一.基础知识 1.jq的使用 在script块中: 方式1:$(function(){                                          $("[使用选择器] ...

  3. TZOJ5255: C++实验:三角形面积

    #include<iostream> #include<iomanip> #include<math.h> #include<cmath> using ...

  4. REST framework之分页组件

    REST framework之分页组件 一 简单分页 查看第n页,每页显示n条 from rest_framework.pagination import PageNumberPagination # ...

  5. AS3事件类型

    Event事件类型: ACTIVATE       激活事件 DEACTIVATE 对象休眠事件 ADDED      可视对象添加事件 ADDED_TO_STAGE 可视对象添加到舞台事件 REMO ...

  6. Roads in the Kingdom CodeForces - 835F (直径)

    大意: 给定一个基环树, 求删除一条环上的边使得直径最小. 直径分两种情况 环上点延伸的树内的直径 两个环上点的树内深度最大的点匹配 第一种情况直接树形dp求一下, 第二种情况枚举删除的环边, 线段树 ...

  7. 可拖拽dialog

    指令的封装转自https://blog.csdn.net/sinat_21902709/article/details/86545444 可拖拽dialog应用于很多弹出框,所以需要作用于全局 在插件 ...

  8. native function 'Window_sendPlatformMessage' (4 arguments) cannot be found

    https://github.com/pauldemarco/flutter_blue/issues/140 https://github.com/flutter/flutter/issues/168 ...

  9. grep过滤日志

    A -B -C 后面都跟阿拉伯数字 -A是显示匹配后和它后面的n行. -B是显示匹配行和它前面的n行. -C是匹配行和它前后各n行. 总体来说,-C覆盖面最大.用它保险些.哈哈.这3个开关都是关于匹配 ...

  10. 【转载】C#使用Random类来生成指定范围内的随机数

    C#的程序应用的开发中,可以使用Random随机数类的对象来生成相应的随机数,通过Random随机数对象生成随机数的时候,支持设置随机数的最小值和最大值,例如可以指定生成1到1000范围内的随机数.R ...