云班课学习内容

一、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. c++修改打印机名称

    public static bool SetPrinterName(string OldName, string newName) { IntPtr hPrinter; PrintAPI.struct ...

  2. 本地yum源 、阿里yum源、163yum源的配置安装

    一.本地yum源 (我使用的7.3版本) 1..添加一个新的yum源配置文件dvd.repo(文件名字自定义) vi etc/yum.repos.d     添加新的内容: name=rhel_dvd ...

  3. Json 文件读写以及和IniFile 转换

    JSON 文件是越来越受欢迎了,以前程序配置文件用Ini,Ini 简练,简单.方便,但是也有不少缺点,比如,没有 JSON 直观,无法存储复杂点的数据类型. 于是乎,我封装了一个TJsonFile 的 ...

  4. python学习-65 继承2-子类中调用父类的方法

    子类中调用父类的方法 1.子类继承了父类的方法,然后想进行修改,那么就需要在子类中调用父类的方法. 2.方法一:父类名 class School: Country = 'china' def __in ...

  5. 基于卷积神经网络的面部表情识别(Pytorch实现)----台大李宏毅机器学习作业3(HW3)

    一.项目说明 给定数据集train.csv,要求使用卷积神经网络CNN,根据每个样本的面部图片判断出其表情.在本项目中,表情共分7类,分别为:(0)生气,(1)厌恶,(2)恐惧,(3)高兴,(4)难过 ...

  6. 平衡二叉树,B树,B+树的概念及区别

    1.平衡二叉树   由来:平衡二叉树是基于二分法的策略提高数据的查找速度的二叉树的数据结构 特点: 1.二叉树:意思是每个节点最多只能有两个子节点 2.平衡:因为平衡二叉树的查询性能与树的高度成正比, ...

  7. 2.9_Database Interface ADO结构组成及连接方式实例

    说通俗点OLE DB和ODBC都是最底层的东西,而ADO对象给我们提供了一个“可视化”和应用层直接交互的组件,ADO对象T通过OLE DB间接取得数据库中的数据,如下图: 从上面看出,可以说ADO是应 ...

  8. 使用activiti的designer插件记录

    1.activiti添加排他网,条件下载condition中 2.activiti添加监听Listener,知道3种方法 1.实现taskListener 通过加载java class的方式去加载实现 ...

  9. 扩展JS

    //JS的扩展方法: 1 定义类静态方法扩展 2 定义类对象方法扩展            var aClass = function(){} //1 定义这个类的静态方法            aC ...

  10. NIO开发Http服务器(2):项目结构

    最近学习了Java NIO技术,觉得不能再去写一些Hello World的学习demo了,而且也不想再像学习IO时那样编写一个控制台(或者带界面)聊天室.我们是做WEB开发的,整天围着tomcat.n ...