云班课学习内容

一、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. 阿里云最新Maven仓库地址 从此 我的maven依赖下载666~

    配置指南 maven配置指南 打开maven的配置文件(windows机器一般在maven安装目录的conf/settings.xml),在<mirrors></mirrors> ...

  2. 内网Https 自签Https证书 配合Tomcat 实现内网Https详细图文

    内网项目启用Https配置手册 软件需求: OpenSSL https://www.openssl.org/ 已经安装了Java Jdk环境 制作前的需求: 已经配置了Jdk环境变量 安装好OpenS ...

  3. DevExtreme学习笔记(一) DataGrid中MVC分析

    @(Html.DevExtreme().DataGrid() .ID("gridContainer") .DataSource(d => d .OData() .Url(&q ...

  4. sql group by hour 按小时分组统计

    Time字段以小时分组统计 select datepart(hour,time) hour,count(1) count from table where Similarity<75 group ...

  5. 深入理解JVM(一) -- 自动内存管理机制

    Java运行时数据区域分为:程序计数器,虚拟机栈,本地方法栈,Java堆,方法区,运行时常量池,直接内存,结构如下: 1.程序计数器: 是一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示 ...

  6. vue 全局挂载组件

    <!-- plugin.js --> import someComponent from './components/someComponent' export default { ins ...

  7. requests模块 简单使用

    目录 requests模块 简单使用 Anaconda简单了解 简单了解 requests模块 使用requests模块 爬取搜狗首页源码数据 实现一个简易的网页采集器 解决乱码问题 解决UA检测问题 ...

  8. Linux (x86) Exploit 开发系列教程之三(Off-By-One 漏洞 (基于栈))

    off by one(栈)? 将源字符串复制到目标缓冲区可能会导致off by one 1.源字符串长度等于目标缓冲区长度. 当源字符串长度等于目标缓冲区长度时,单个NULL字节将被复制到目标缓冲区上 ...

  9. xcode 手动管理内存 的相关知识点总结

    一.XCode4.2以后支持自动释放内存ARC xcode自4.2以后就支持自动释放内存了,但有时我们还是想手动管理内存,这如何处理呢. 很简单,想要取消自动释放,只要在  Build Setting ...

  10. jenkins 启动

    docker pull jenkinsci/blueocean docker run \ -u root \ --rm \ -d \ -p 8888:8080 \ -p 50000:50000 \ - ...