memcpy Linux内核实现引发的思考:为什么嵌入式汇编中不用指定段寄存器

(2013-05-18 18:42:25)

标签:

内核

汇编

指定

杂谈

memcpy

Linux内核实现引发的思考:为什么嵌入式汇编中不用指定段寄存器最近买了王爽的汇编语言和Linux内核完全注释,准备开始好好学习一下汇编语言,并看看早期的Linux(0.11版本)源代码实现。

之前舍友面试TX是被问过memcpy什么时候不能用,这种问题如何解决?

答:当dest,src都指向同一个数组且dest>src,那么当n大于abs(dest >

src),则这个时候最后m=(n - abs(dest >

src))个字节会被覆盖。可以用memmove来规避这种问题,因为memmove有对dest和src大小进行判断,根据不同的结果进行升序拷贝(dest

< src)和逆序拷贝(dest >= src)。

memcpy Linux(0.11版本)源代码实现如下:

extern inline void * memcpy(void * dest, const void * src, int

n)

{

__asm__ ("cld\n\t"

"rep\n\t"

"movsb"

::"c"(n),"S"(src),"D"(dest)

:"cx","si","di");

return dest;

}

我们可以发现memcpy是从源地址直接到目的地址的逐字节的升序拷贝。因为是逐字节的升序拷贝,所以但拷贝的指针是指向同一个数#20540;时可能会出现问题。

让我们再来看一下memmove的Linux(0.11版本)源代码实现如下:

extern inline void * memmove(void * dest, const void * src, int

n)

{

if (dest < src)

{

__asm__ ("cld\n\t"

"rep\n\t"

"movsb"

::"c"(n),"S"(src),"D"(dest)

:"cx","si","di");

}

else

{

__asm__ ("std\n\t"

"rep\n\t"

"movsb"

::"c"(n),"S"(src #43; n - 1),"D"(dest #43; n - 1)

:"cx","si","di");

}

return dest;

}

我们发现memmove并没有判断dest和src是否指向同一数组(实际上也无法判断),而是判断dest和src之间的大小关系,并根据大小比较结果采取不同的拷贝策略,当dest小于src采用升序拷贝,否则采用逆序拷贝。

到这里思考就结束了?其实并没有,我们可以看看一下这两个实现对应的汇编代码。这里我只看了memcpy的汇编代码,下面我截取了memcpy

对应的汇编代码的实现(gcc -S test.c来获取test.c对应的汇编代码):

5 memcpy:

6 pushl �p

7 movl %esp, �p

8 pushl �i

9 pushl %esi

10 pushl �x

11 movl 16(�p), �x

12 movl 12(�p), �x

13 movl 8(�p), �x

14 movl �x, �x

15 movl �x, %esi

16 movl �x, �i

17 #APP

18 # 5 "t.c" 1

19 cld

20 rep movsb

21 # 0 "" 2

22 #NO_APP

23 movl 8(�p), �x

24 popl �x

25 popl %esi

26 popl �i

27 popl �p

28 ret

最为关键的几行汇编代码如下:

14 movl �x, �x

15 movl �x, %esi

16 movl �x, �i

17 #APP

18 # 5 "t.c" 1

19 cld

20 rep movsb

17,18行为gcc嵌入的注释,可以无视,学过8086汇编的人都知道对内存地址的访问需要知道段地址和偏移地址,可是对应memcpy的汇编代码并没有显示地对es和ds这连个寄存器进行赋#20540;,刚开始以为段地址是在调用memcpy前调用,为了证实这个猜想写了个demo程序,在main函数中调用memcpy函数,并用gcc把源代码转换成汇编代码,查看了源代码发现,在调用memcpy前并没有设置es和ds这两个段寄存器。后面我陷入了困惑,问题一直没有解开。

后面在看《深入理解计算机系统书》的第三章时,发现了这样的描述“最初的8086的存储器模型和它在80286中的扩展都已经过时了,作为替代按摩椅导购网,Linux使用了平面寻址方式(flat

addressing),在这种寻址方式中,程序员将整个存储空间看做一个大的字节数组”,心想难道段寄存器不用设置了,也不用段寄存器了?

在好奇心的驱动下搜索了“平面寻址

不需要段地址?”看了第一篇文章(),最后的几行描述是“Windows操作系统为用户程序“安排好了一切”。具体表现在为用户程序的代码段、数据段和堆栈段全部预定义好了段描述符。这些段的起始地址为0,限长为ffffffff,所以用它们可以直接寻址全部的4

GB地址空间。程序开始执行的时候,CS,DS,ES和SS都已经指向了正确的描述符,在整个程序的生命周期内,程序员不必改动这些段寄存器,也不必关心它们的#20540;究竟是多少(实际上,想改也改不了)。

答案终于揭晓:“程序开始执行的时候,CS,DS,ES和SS都已经指向了正确的描述符,在整个程序的生命周期内,程序员不必改动这些段寄存器,也不必关心它们的#20540;究竟是多少(实际上,想改也改不了)。”

总结:我学的8086是早期的汇编,gcc 转换而成的汇编是基于IA32(Intel Architecture

32-bit)的汇编,寻址方式已经发生了改变。要猜想,并去验证。

分享:

喜欢

0

赠金笔

加载中,请稍候......

评论加载中,请稍候...

发评论

登录名: 密码: 找回密码 注册记住登录状态

昵   称:

评论并转载此博文

发评论

以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

linux内核编程memcpy,memcpy Linux内核实现引发的思考:为什么嵌入式汇编中不用指定段寄存器...相关推荐

  1. Linux系统编程:验证kernel内核缓存区大小->4096字节

    Linux系统编程:验证kernel内核缓存区大小->4096字节 李四老师 于 2018-04-04 00:40:04 发布 2778 收藏 2 分类专栏: [Linux编程] [C/C++编 ...

  2. 嵌入式学习之linux系统编程----1 了解linux编程并且在ubuntu以及ARM上运行测试程序

    1.何为linux系统编程? linux系统编程也称为linux下的高级编程,它介于应用层与驱动层之间. 一般来说分为三个层面,分别是:应用层(写一个qt程序或者c程序就属于是应用层面).驱动层(比如 ...

  3. linux netlink 编程示例(一)内核端

    Netlink是一种内核层与应用层通信的一种机制,比如说在做一个内核模块的时候,往往会需要应用层提供一些配置信息,这时候就可以使用netlink.netlink包括内核层和应用层,内核层注册一个net ...

  4. linux环境编程从应用,linux环境编程:从应用到内核

    <UNIX环境高级编程>(简称APUE)几乎是Linux领域程序员人手必备的一本书.但在掌握和理解APUE的内容后,又该如何继续提高自己的技能,如何更深入地理解Linux环境编程及其背后的 ...

  5. linux环境编程 学习,学习linux环境高级编程首先学习的是文件的操作。因为有.pdf...

    学习linux环境高级编程首先学习的是文件的操作.因为有 学习 Linux 环境高级编程,首先学习的是文件的操作.因为有一句很有趣的话"Linux 下一切皆文件".所以掌握了文件操 ...

  6. 【Linux系统编程学习】Linux进程控制原语(fork、exec函数族、wait)

    此为牛客Linux C++和黑马Linux系统编程课程笔记. 1. fork函数 1.1 fork创建单个子进程 #include<unistd.h> pid_t fork(void); ...

  7. 《Linux游戏编程》——理解Linux文件系统标准

    Linux游戏编程 Programming Linux Games [美]John R. Hall 著 作者:[美]John R. Hall 单位:Loki Software, Inc. 时间:200 ...

  8. 林世霖. linux环境编程图文指南,linux环境编程图文指南

    linux环境编程图文指南是一本linux编程环境配置指南,由林世霖.钟锦辉和李建辉三人共同编著.本书定位Linux环境编程入门与提高,全书拥有近400余幅案例图表,200多篇源代码,作者很多编程初入 ...

  9. 【Linux系统编程应用】 Linux Input子系统(一)

    1. 什么是输入子系统 ? 输入子系统是 Linux内核用于管理各种输入设备 (键盘,鼠标,遥控杆,书写板等等 )的部分,用户通过输入子系统进行内核,命令行,图形接口之间的交换.输入子系统在内核里实现 ...

最新文章

  1. Web 安全漏洞之 XSS 攻击,Java 开发必看!
  2. Springboot 连接数据库
  3. VTK:Filtering之Glyph3D
  4. Python 使用ntplib库同步校准当地时间的方法 (NTP)
  5. php中%3c w() %3e,DedeCMS V5.7 SP2后台存在代码执行漏洞
  6. Java转C#的最佳工具
  7. Ubuntu下安装Nginx服务器并进行优化
  8. 在Windows NT上装还原卡
  9. 【软考】软件设计师知识点整理(待更新)
  10. 协整理论与面板数据分析
  11. 计算机机房运行环境条件要求,机房环境都有哪些要求
  12. 桌面上的计算机打不开怎么办,电脑桌面计算机打不开怎么办
  13. 模式识别和计算机科学与技术,模式识别与智能系统
  14. spring boot网上眼镜商场毕业设计-附源码241659
  15. python爬虫之英汉互译(爬虫+pyqt5)
  16. java版阿里云发送短信
  17. 一文带你了解什么是PACS系统源码
  18. Dorado5学习笔记
  19. ios 自动打包命令_iOS Xcode 自动打包,一键上传AppStore脚本
  20. 昼短苦夜长,何不秉烛游

热门文章

  1. Rainbow Bridge:trustless bridge between NEAR and Ethereum
  2. 2021-03-30 CodeCraft-21 and Codeforces Round #711 (Div. 2)
  3. 关于CSDN这个名字
  4. vs + opencv + YOLO-Fastest 目标检测
  5. python爬虫-使用cookie登录
  6. linux 失能鼠标,Linux内核中CPU主频和电压调整 (一)
  7. 实时操作系统的滴答Tick设置多少才合适?
  8. IDEA小技巧——Shelve
  9. 2022年深圳杯A题破除“尖叫效应”与“回声室效应”走出“信息茧房”
  10. ubuntu更换内核版本