封开| 库车| 金山| 清苑| 新龙| 黄岩| 昌乐| 尖扎| 青川| 比如| 黄石| 霍城| 四方台| 新邱| 陈仓| 昌都| 奈曼旗| 保定| 眉县| 鄯善| 筠连| 京山| 科尔沁左翼后旗| 攀枝花| 安仁| 勉县| 繁峙| 庐山| 青田| 瑞金| 唐河| 襄垣| 察隅| 邻水| 保山| 唐海| 花莲| 巫溪| 尉犁| 安仁| 绛县| 涟源| 阳泉| 闽侯| 达孜| 新干| 广昌| 盐都| 古交| 茂县| 魏县| 保靖| 覃塘| 南靖| 呼和浩特| 大同区| 龙胜| 昭觉| 东港| 凭祥| 瑞金| 台北市| 寿光| 沁阳| 壤塘| 嘉鱼| 苍梧| 海盐| 武穴| 勃利| 和平| 让胡路| 平湖| 温泉| 五河| 来宾| 肥东| 双辽| 洪湖| 五峰| 成武| 全椒| 肃南| 万年| 盐池| 泽库| 巧家| 北安| 孟连| 称多| 海林| 天镇| 阳高| 镶黄旗| 利辛| 静乐| 巴里坤| 合浦| 达尔罕茂明安联合旗| 临泽| 紫阳| 富川| 舞阳| 昭平| 昌邑| 长泰| 若羌| 囊谦| 富民| 冕宁| 紫云| 筠连| 永靖| 魏县| 泽库| 伊通| 尤溪| 辛集| 晴隆| 察哈尔右翼前旗| 周至| 缙云| 西畴| 东川| 潜江| 湄潭| 弥勒| 兰溪| 子洲| 金沙| 宕昌| 文水| 崂山| 锡林浩特| 黑河| 涡阳| 淮阳| 金川| 利辛| 进贤| 贵池| 武清| 南乐| 大宁| 杭州| 门头沟| 博山| 泽库| 城口| 宣城| 克拉玛依| 江陵| 洋县| 范县| 麟游| 特克斯| 峨眉山| 孝义| 乳山| 柳州| 鄂温克族自治旗| 化州| 高青| 镇安| 康乐| 雄县| 勐腊| 十堰| 顺德| 渭南| 太康| 五常| 平阴| 行唐| 原平| 炉霍| 陈巴尔虎旗| 电白| 芮城| 铁岭县| 岱岳| 蕉岭| 南宫| 酒泉| 固阳| 威远| 德清| 任县| 北流| 高邑| 建瓯| 工布江达| 嘉义市| 汤原| 嫩江| 迭部| 周至| 景谷| 商南| 宾川| 大方| 吉安县| 安福| 丰润| 伽师| 乐业| 扎鲁特旗| 保亭| 正宁| 鄂尔多斯| 子长| 盘锦| 五河| 元阳| 敦化| 布拖| 小金| 沙县| 庐山| 原平| 天水| 玉门| 湟源| 绍兴市| 织金| 扶余| 剑川| 百色| 夏县| 洛川| 阿拉善右旗| 贵州| 安乡| 临漳| 普兰店| 丰顺| 巨野| 黔江| 容县| 临邑| 永福| 单县| 毕节| 南宫| 海淀| 浦口| 沿滩| 西盟| 长兴| 代县| 大竹| 海沧| 保德| 苏尼特右旗| 远安| 集安| 睢宁| 大同县| 华安| 南城| 铁力| 曲江| 嘉义市| 贵港|

一图了解《食品安全标准与监测评估“十三五...

2019-10-18 09:56 来源:宜宾新闻网

  一图了解《食品安全标准与监测评估“十三五...

  刘继伟说,他们还将建立自有充电站,设立洗车点、咖啡屋等方便市民。据合富大数据统计,广州租房均价稳中有升,从去年广州全市的二手住宅租赁市场来看,均价为元/平方米/月,同比小幅上涨%。

此外,“意见”还要求加大惩戒力度,凡是拒绝或变相拒绝职工办理住房公积金贷款的,一经查实,将责令限期整改,拒不整改的记入企业信用档案,同时,利用南京市“七日双公开”信息采集平台导入“信用中国网”,将相关单位列入严重失信类黑名单。对于房企无正当理由未在10个工作日内签订按揭协议的,将视为违规,并予以查处且记录在案。

  观点地产新媒体查阅公告,2017年,祈福生活的毛利由2016年的亿元增至2017年的亿元,相当于增加百万元或%;毛利率于2016年及2017年分别为%及%。自2017年下半年以来,我国在几大试点城市推行租售并举的政策,发展市场。

  按照计划,6月底前,喜尔客共享汽车将达到600辆,直营网点上百个,年底前,喜尔客车辆有望达到2000辆。看点02河西一地块闲置8年,成共享单车处理场南京河西核心区一幅地块闲置多年,现在竟然成为共享单车的处理场?该幅地块位于河西大街明基医院斜对面、缤润汇南侧,2010年被一家名为瀚海房地产的开发商拿下,拿地之后的8年时间里长期闲置,曾开工之后又停工。

长安街及其延长线以国家行政、军事管理、文化、国际交往功能为主,体现庄严、沉稳、厚重、大气的形象气质。

  “现在客户比较多,房源少,您要是可以再等等,说不定年中房源多了,就便宜些了。

  到2020年,完成对82座山体的改造,其中绿化提升62座山体,建成山体公园20处,实现城区山体绿化全覆盖。总而言之,房地产长效机制现在已经初现苗头了,房地产市场长效机制的建立也依然发芽开始了,到时,人人买得起房,不再是梦,一切就让我们拭目以待吧!

    广州和天津保持着2016年的同样位势,分获综合排名第4和第5位。

  按理说,他们手里囤积的房子应该大量出手兜售了,那么为什么除了一些调空比较严的地方有所举动,其他的地方难道都在坐以待毙吗?小编总结了下列三点,估计吃瓜群众都没有想到吧!第一,税负转嫁很多城市里大部分楼盘都已经卖完了,然而晚上一片漆黑,这说明这些房子其实都是在炒房客手里的,所以说炒房者手里的房子的空置率有多高,我们一目了然,房产税的出台要收割一大批炒房客,但是也有人说“税负转嫁”,把税负算在房价里,这一招可以说非常高明!第二,空房出租对于炒房客来说,到目前为止,即使房价不涨,持有一套房子的成本也并不高,房子在自己手里,除了交点极少的物业费外,基本面没有任何得额外支出。位于金融城的佳兆业逸灏苑为复式产品,27层以下为83-98平方米的小面积复式,27层以上为156-323平方米的大面积复式,网签均价接近5万元/平方米。

  年内,祈福生活的收入由2016年的亿元增加至2017年的亿元,相当于增加3820万元或%。

  在河西大街这幅地块的现场,整个地块被高高的围墙包围,东侧大门紧锁,西侧围墙上贴着一张“区施工工地扬尘污染控制公示牌”,常年被风吹日晒后公告牌四分五裂,从模糊的字迹中可以辨认出这幅地块为河西中部地区33-2号地块,建设单位南京瀚海房地产,施工单位江苏长江机械化基础工程公司。

  据了解,南京公积金管理中心还列出了三类情况下,买房人所购的楼盘确实不具备签订协议的条件,分别是:楼盘因所在土地已设抵押;土地用途为商用;销售房产为独幢、类独幢、联排住宅。)家粉那么,该如何查询学位是否被占用?一般来说,有以下几种方式:1.有些中介可以帮忙查;2.街道办会有相关信息;3.到公安局户籍科查近期该户籍地址下有没有适龄儿童户口调入调出;4.到学校查。

  

  一图了解《食品安全标准与监测评估“十三五...

 
责编:
Chinaunix首页 | 论坛 | 博客
  • 博客访问: 866596
  • 博文数量: 53
  • 博客积分: 1165
  • 博客等级: 下士
  • 技术积分: 1807
  • 用 户 组: 普通用户
  • 注册时间: 2019-10-18 14:56
个人简介

专注于操作系统内核的实现

文章分类
文章存档

2015年(2)

2014年(16)

2013年(18)

2012年(17)

分类: C/C++

2019-10-18 12:54:51


         hello world程序绝对经典的让人落泪,这是很多人的第一个程序。这个程序在Brian KernighanDennis M. Ritchie合著的《The C Programme Language》中使用而广泛流行。该程序也体现了两位作者心向世界的博大情怀。

         本人编程也是从hello world程序开始的,但是我很多人写的hello world程序都需要库和操作系统的支持才能运行。今天我想来用C语言重新实现一个裸机版hello world程序,即不需要操作系统和库的支持,顺便纪念一下hello world程序和C语言。

         首先看看实现裸机版的hello world程序所需要的工具:

  1. LINUX操作系统

  2. 编译器:GCCLDnasm

  3. 文件编辑器

  4. Make

  5. GRUB引导器(安装LINUX时已经自带了)

下面我们从上向下完成hello world程序,首先来写好main函数,如下:

点击(此处)折叠或打开

  1. void main()
  2. {
  3.     printf("hello world!");
  4.     return;
  5. }


是不是很熟悉,这样的程序,我想很多人闭着眼一通盲码,都可以正确无误

好了,上面的代码依然是调用了printf函数输出“hello world!”字符串的,由于这裸机版的程序,所以不能调用库中的printf函数,而是要自己亲自实现该函数。下面就去实现一个最简单的printf函数。如下:

点击(此处)折叠或打开

  1. void printf(char* fmt,...)
  2. {
  3.     _strwrite(fmt);
  4.     return;
  5. }


确实够简单了,没有像通常的printf函数处理多个参数,也没有对参数进行格式化处理,而是调用了_strwrite函数,下面接着实现_strwrite函数,如下:

点击(此处)折叠或打开

  1. void _strwrite(char* string)
  2. {
  3.     char* p_strdst=(char*)(0xb8000);
  4.     while(*string)
  5.     {
  6.         *p_strdst=*string++;
  7.         p_strdst+=2;
  8.     }
  9.     return;
  10. }


_strwrite函数才是输出字符串的核心函数,它把字符串的每个字符,依次写入以0xb8000为开始地址的内存空间,这个内存空间默认映射是显卡的显存,并且我们知道计算机启动时显卡默认工作在字符模式下。对应于屏幕是每行80个字符,一共有25行。

         可是有了这些代码就可以了吗,当然不行,因为是裸机,所以在调用C函数之前,还要初始化栈和CPU的一些寄存器,更为关键的是我们的程序要被GRUB引导加载,而这些动作用C语言又无法实现,这时我们的大汇编语言就该上场了,发挥它神奇的作用了,下面来用汇编语言写一段代码,如下:

点击(此处)折叠或打开

  1. MBT_HDR_FLAGS    EQU 0x00010003
  2. MBT_HDR_MAGIC    EQU 0x1BADB002
  3. MBT_HDR2_MAGIC    EQU 0xe85250d6
  4. global _start
  5. extern main
  6. [section .start.text]
  7. [bits 32]
  8. _start:
  9.     jmp _entry
  10. ALIGN 8
  11. mbt_hdr:
  12.     dd MBT_HDR_MAGIC
  13.     dd MBT_HDR_FLAGS
  14.     dd -(MBT_HDR_MAGIC+MBT_HDR_FLAGS)
  15.     dd mbt_hdr
  16.     dd _start
  17.     dd 0
  18.     dd 0
  19.     dd _entry

  20. ;以上是GRUB所需要的头
  21. ALIGN 8
  22. mbt2_hdr:
  23.     DD    MBT_HDR2_MAGIC
  24.     DD    0
  25.     DD    mbt2_hdr_end - mbt2_hdr
  26.     DD    -(MBT_HDR2_MAGIC + 0 + (mbt2_hdr_end - mbt2_hdr))
  27.     DW    2, 0
  28.     DD    24
  29.     DD    mbt2_hdr
  30.     DD    _start
  31.     DD    0
  32.     DD    0
  33.     DW    3, 0
  34.     DD    12
  35.     DD    _entry
  36.     DD 0
  37.     DW    0, 0
  38.     DD    8
  39. mbt2_hdr_end:
  40. ;以上是GRUB2所需要的头
  41. ;包含两个头是为了同时兼容GRUB、GRUB2

  42. ALIGN 8

  43. _entry:
  44.     ;关中断
  45.     cli
  46.     ;关不可屏蔽中断
  47.     in al, 0x70
  48.     or al, 0x80
  49.     out 0x70,al
  50.     ;重新加载GDT
  51.     lgdt [GDT_PTR]
  52.     jmp dword 0x8 :_32bits_mode

  53. _32bits_mode:
  54.     ;下面初始化C语言可能会用到的寄存器
  55.     mov ax, 0x10
  56.     mov ds, ax
  57.     mov ss, ax
  58.     mov es, ax
  59.     mov fs, ax
  60.     mov gs, ax
  61.     xor eax,eax
  62.     xor ebx,ebx
  63.     xor ecx,ecx
  64.     xor edx,edx
  65.     xor edi,edi
  66.     xor esi,esi
  67.     xor ebp,ebp
  68.     xor esp,esp
  69.     ;初始化栈,C语言需要栈才能工作
  70.     mov esp,0x9000
  71.     ;调用C语言函数main
  72.     call main
  73.     ;让CPU停止执行指令
  74. halt_step:
  75.     halt
  76.     jmp halt_step


  77. GDT_START:
  78. knull_dsc: dq 0
  79. kcode_dsc: dq 0x00cf9e000000ffff
  80. kdata_dsc: dq 0x00cf92000000ffff
  81. k16cd_dsc: dq 0x00009e000000ffff
  82. k16da_dsc: dq 0x000092000000ffff
  83. GDT_END:

  84. GDT_PTR:
  85. GDTLEN    dw GDT_END-GDT_START-1
  86. GDTBASE    dd GDT_START



这段代码不必多说,上面的注释已经写的很好了,汇编程序代码也写好了,最后的工作就是编译链接程序了,编译还好说,但是链接就不能用通常链接应用程序的方法了,因为这时裸机程序,所以我们得写个链接脚本来控制链接过程,如下:

点击(此处)折叠或打开

  1. ENTRY(_start)
  2. OUTPUT_ARCH(i386)
  3. SECTIONS
  4. {
  5. . = 0x200000;
  6. __begin_start_text = .;
  7. .start.text : ALIGN(4) { *(.start.text) }
  8. __end_start_text = .;
  9. __begin_text = .;
  10. .text : ALIGN(4) { *(.text) }
  11. __end_text = .;
  12. __begin_data = .;
  13. .data : ALIGN(4) { *(.data) }
  14. __end_data = .;
  15. __begin_rodata = .;
  16. .rodata : ALIGN(4) { *(.rodata) *(.rodata.*) }
  17. __end_rodata = .;
  18. __begin_kstrtab = .;
  19. .kstrtab : ALIGN(4) { *(.kstrtab) }
  20. __end_kstrtab = .;
  21. __begin_bss = .;
  22. .bss : ALIGN(4) { *(.bss) }
  23. __end_bss = .;
  24. }


上面的链接脚本最关键的是告诉LD链接器,我们的程序从0x200000的内存地址开始运行。最后还要写个makefile控制编译、链接过程。如下:

点击(此处)折叠或打开

  1. MAKEFLAGS = -sR
  2. MKDIR = mkdir
  3. RMDIR = rmdir
  4. CP = cp
  5. CD = cd
  6. DD = dd
  7. RM = rm
  8. ASM = nasm
  9. CC = gcc
  10. LD = ld
  11. ASMBFLAGS = -f elf
  12. CFLAGS = -c -Os -std=c99 -m32 -Wall -Wshadow -W -Wconversion -Wno-sign-conversion -fno-stack-protector -fomit-frame-pointer -fno-builtin -fno-common -ffreestanding -Wno-unused-parameter -Wunused-variable
  13. LDFLAGS = -s -static -T hello.lds -n --oformat binary
  14. PMHELLO_OBJS :=
  15. PMHELLO_OBJS += entry.o helkrlmain.o vgastr.o
  16. PMHELLO_BIN = pmhello.bin
  17. .PHONY : build clean all link
  18. all: clean build link
  19. clean:
  20. $(RM) -f *.o *.bin
  21. build: $(PMHELLO_OBJS)
  22. link: $(PMHELLO_BIN)
  23. $(PMHELLO_BIN): $(PMHELLO_OBJS)
  24. $(LD) $(LDFLAGS) -o $@ $(PMHELLO_OBJS)
  25. %.o : %.asm
  26. $(ASM) $(ASMBFLAGS) -o $@ $<
  27. %.o : %.c
  28. $(CC) $(CFLAGS) -o $@ $<


安装测试,在linux系统下则非常方便,因为linux系统已经安装好了GRUB2,默认情况下,只要把pmhello.bin文件复制到linux系统的/boot/目录下,同时修改/boot/grub/目录下的grub.cfg文件。如下图所示:

 

重启计算机就可以看到PMHELLO启动选项了……

该项目代码地址是:https://code.csdn.net/lmnos/pmhelloworld

阅读(101893) | 评论(14) | 转发(15) |
给主人留下些什么吧!~~

wodemaya20192019-10-18 08:15:09

厉害呀,前辈,这个程序安装到u盘,是不是就能开机启动呢

frankey20092019-10-18 12:38:17

这个牛逼了

lmnos2019-10-18 13:35:26

leon_yu:这篇文章怎么还在首页啊,CU小编春节放假几个月?

这我就不知道?

回复 | 举报

leon_yu2019-10-18 17:31:16

这篇文章怎么还在首页啊,CU小编春节放假几个月?

lmnos2019-10-18 22:30:30

qfire:哥,你的内功好深厚!,能否介绍一些书籍给小弟学习一下(有关操作系统内核开发方面的),非常感谢!

这只是一点小case 到时看我的书吧

回复 | 举报
评论热议
请登录后评论。

登录 注册

万盛区 武定县 南千章胡同 北边渠 平阳坑镇
白家楼 茂兰彝族布朗族镇 砖楼村 金川镇 阳高县 花溪镇 吴炉镇 刚毅胡同 双桥镇 魏家屯 路易斯安那州 大丰路 松桥 二环西路 塔里木盆地 纺织厂 松园村 大荣乡 沙坡头区 春园社区 农七师一二九团 巴彦红格尔嘎查