手机上的arm格式怎么在电脑中mkv格式无法播放放?

谁能写给我所有的视频播放格式大全_百度知道
谁能写给我所有的视频播放格式大全
提问者采纳
图像质量好,而且是在 H,视频格式追求的无非是压缩率和图像质量,所以它的图像质量比VCD 差一点点并不出奇,Chrome 不要说,而制定出不同的压缩比率、DIVX等比是不敢恭维的啦,它的出现有效地解决了视频文件导入Flash后.2 GB 左右大小、多语言支持,NAVI 是一种去掉视频流特性的改良型ASF 格式、RAM)格式由一开始就是定位在视频流应用方面的,打破了原先RM格式那种平均压缩采样的方式。3GP3GP是一种3G流媒体的视频编码格式,属正常现象,推出了可变比特率编码的RMVB格式,一般而言一部120分钟的dvd体积为4GB、Opera 都已经表态将会支持这个新格式,具有体积小、Broadcom,使用MPEG-1 的压缩算法。WMV的主要优点在于,但在MP4播放器中。对于MP4.264编码的高清晰视频。简单的说、自适应多速率 (AMR) 和MPEG-4 和H,大家应该都知道。MPEG系列标准对VCD,也可以说是视频流技术的始创者、ARM,但如果你另外下载并安装了 VP8,Ogg Vorbis 本来就是开放格式,但却久久未有能够完全兼容RMVB格式的机型诞生,采用基于内容的压缩编码;IEC 14496)则是基于第二代压缩编码技术制定的国际标准,可以把一部120 分钟长的电影压缩到1、可伸缩的媒体类型,大部分的VCD都是用MPEG1 格式压缩的( 刻录软件自动将MPEG1转换为DAT格式 ) ,而且清晰度流畅度并不比原DVD差太远,这是F4V格式的另一个特点,或许 WebM 真有机会迅速地站稳脚跟,那你就要考虑是不是碰到了n AVI。MP4发展的整整七个年头里,其中Google将其拥有的VP8视频编码技术以类似BSD授权开源,怎样的视频格式才将会是其未来的主流呢。MPEG-1相信是大家接触得最多的了?Intel、手持式装置等上面顺畅地使用。ASF 是MICROSOFT 为了和的Real player 竞争而发展出来的一种可以直接在网上观看视频节目的文件压缩格式。它可以在用56K MODEM 拨号上网的条件实现不间断的视频播放,可能每一位电脑使用者(或许就包括正在阅读这篇文章的您)电脑中的视频文件,成为目前PC中最广泛存在的视频格式,其重点是解决视频服务这一核心的网络用户体验,这方面是ASF的有力竞争者,因此 WebM 应该是不会有 H,为了节约用户电脑硬盘宝贵的空间容量。实际上。FLVFLV是FLASH VIDEO的简称。n AVI是New AVI 的缩写,其图像质量和MPEG2,是一个名为Shadow Realm 的地下组织发展起来的一种新视频格式。F4V作为一种更小更清晰,而F4V则支持H,是非常不容易的,使用户能使用手机享受高质量的视频.MOV和基于MPEG压缩法的*,是应用最广泛,尤其是容量小价格便宜的闪存MP4而言、战争等),更利于在网络传播的格式,取得的 Video Codec、3IVX,至于 VP8 则是 Google 当年买下一间叫 On2 的公司的时候、tablet、DVD等视听消费电子及数字电视和高清晰度电视(DTV&&HDTV)。其核心由包括高级音频编码(AAC),让NAVI 可以拥有更高的帧率,超过80%都会是RMVB格式。由于它形成的文件极小,但比同是视频“流”格式的RAM 格式要好、NVIDIA:可扩充的媒体类型。ASFASF(Advanced Streaming format高级流格式)。而为了实现更优化的体积与画面质量,这种先进的,就是我们所说的更清晰更流畅; VP8 的影片,它们是Real Networks公司所制定的音频视频压缩规范,而不需要通过转换等复杂的方式,已越来越多的视频被压制成了RMVB格式,该格式是“第三代合作伙伴项目”(3GPP)制定的一种多媒体标准,可以是常见的DivX,以实现数字视音频,并支持更高比特率.264 正因为其非开放性而备受质疑的时候。RMVBRMVB的前身为RM格式,采用浮动比特率编码的方式,使得网络观看视频文件成为可能,它可在一个文件中集成多条不同类型的音轨和字幕轨、开放的视频格式。AVI这个由微软公司发表的视频格式。 WebM标准的网络视频更加偏向于开源并且是基于HTML5标准的,目前大部分支持视频拍摄的手机都支持3GPP格式的视频播放,也是目前手机中最为常见的一种视频格式.263视频编码解码器等组成、处理上面也有相当多的应用,音频视频交错(Audio Video Interleaved)的英文缩写。其特点是网速占用较少,码率最高可达50Mbps。也就是说F4V和FLV在同等体积的前提下、扩展性等,WebM 项目旨在为对每个人都开放的网络开发高质量,在视频领域可以说是最悠久的格式之一、XviD,里面包括了 VP8 影片轨和 Ogg Vorbis 音轨,Real Networks公司不久又在RM的基础上, 即可以支持静态的*。  要推动一个新格式进入主流、QuickTime。Quick-Time提供了两种标准图像和数字视频格式,那当然你也可以播放 HTML &#47。F4V是Adobe公司为了迎接高清时代而推出继FLV格式后的支持H。人们为了缩短视频文件在网络进行传播的下载时间。早期的RM格式为了能够实现在有限带宽的情况下,压缩率和图像的质量都很不错。Youtube 也会支持 WebM 的播放。WebM由Google提出、加载速度极快.264的F4V流媒体格式,在保证平均压缩比的基础上。我们可以做个简单对比,并广为流传、TI 等,也已经被大多数主流播放器兼容播放。AVI格式调用方便,FLV流媒体格式是一种新的视频格式,但画质较差。但 WebM 和 VP8 的推动者是 Google,不能在网络上很好的使用等缺点,能够实现更高的分辨率。Ogg Vorbis 本来就是开放格式,主要是为了配合3G网络的高传输速度而开发的,它是一种全称为Matroska的新型多媒体封装格式、飞车。RMVB由于本身的优势、Qualcomm,FLV格式采用的是H263编码。另外。使用MPEG-2 的压缩算法压缩一部120 分钟长的电影可以压缩到5-8 GB 的大小(MPEG2的图像质量是MPEG-1 无法比拟的),而在静态画面中则灵活地转为较低的采样率。因为ASF 是以一个可以在网上即时观赏的视频“流”格式存在的。NAVI如果发现原来的播放软件突然打不开此类格式的AVI文件,仅400MB左右,而rmvb格式来压缩、也是应用时间最长的格式之一,画质也还不错的优点,出厂时仅会支持 H,是一个开放、音频等多媒体内容。谁不在上头。在 Browser 方面。这类格式包括了MPEG-1。RMVB的诞生,压缩标准可任意选择,甚至成为龙头老大。WMV一种独立于编码方式的在Internet上实时传播多媒体的技术标准。Google 说 WebM 的格式相当有效率,动态的基于Indeo压缩法的*,最终拥有了近乎完美的接近于DVD品质的视听效果,从而合理地利用了比特率资源.PIC和*。MPEG-2 则是应用在DVD 的制作。它和FLV主要的区别在于.MPG视频格式,观看时可明显感觉到这种实为F4V的FLV有明显更高的清晰度和流畅度,所以 NAVI 为了追求这个目标, Google 也把这个 Codec 以类似 BSD 授权放出来,Firefox。REAL VIDEOREAL VIDEO(RA。MKV一种后缀为MKV的视频文件频频出现在网络上,使导出的SWF文件体积庞大,MPEG-2和MPEG-4在内的多种视频格式。它是由Microsoft ASF 压缩算法的修改而来的(并不是想象中的AVI)?我们不妨来探讨一番,Microsoft公司希望用其取代QuickTime之类的技术标准以及WAV、免费的媒体文件格式;DATMPEG(运动图像专家组)是Motion Picture Experts Group 的缩写,并一度红遍整个互联网MPEG&#47,而且其视频编码的自由度也非常大、熵编码及运动补偿等第一代数据压缩编码技术、图形合成应用及交互式多媒体的集成,根据不同的网络传输速率,当然。可以这样说、Freescale。来自产业界的有 Adobe -- Flash Player 将会支持 WebM 格式的播放 -- AMD。WebM 影片格式其实是以 Matroska(即 MKV)容器格式为基础开发的新容器格式、AVI之类的文件扩展名.264 影片的播放,进行视频在线播放而被研发出来。毕竟要实现在网上传输不间断的视频是需要很大的频宽的、WMV 这类流式视频,它以视听媒体对象为基本单元。AVIAVI,使RMVB最大限度地压缩了影片的大小。微软IE9 的支持就没这么直接、变换编码,虽然早就可以做到完美支持AVI格式,从而实现在低速率的网络上进行影像数据实时传送和播放,同时在一些HDTV(高清晰电视广播)和一些高要求视频编辑;MPG&#47,改善了原始的ASF 格式的一些不足。MPEG系列标准已成为国际上影响最大的多媒体技术标准。到如今,一举成为新一代的影片通用格式呢,很多主流媒体网站上下载的F4V文件后缀却为FLV、流的优先级化,F4V已经逐渐取代了传统FLV、开放的封装格式已经给我们展示出非常好的应用前景,其中MPEG-1和MPEG-2是采用相同原理为基础的预测编码.264 的那些潜在的专利问题、本地或网络回放,因为其正在被广泛地应用在VCD 的制作和一些视频片段下载的网络应用上面,甚至可以是RealVideo,将较高的比特率用于复杂的动态画面(如歌舞.JPG图像格式、多媒体通信等信息产业的发展产生了巨大而深远的影响;MPEG-4(ISO&#47。ASF使用了MPEG4 的压缩算法。MOV使用过Mac机的朋友应该多少接触过QuickTime,RMVB格式却长期得不到重视,应该可以在 netbook。QuickTime原本是Apple公司用于Mac计算机上的一种图像视频处理软件
提问者评价
其他类似问题
为您推荐:
其他2条回答
如果怕麻烦可以用19L的那个。推荐15L那个,那个也很好的,用几次就明白了。不过我记不太清它是不是英文的了。其实要用到的几个按钮都是比较简单的英文,它转换手机视频比一般的转换器转换出来质量好,清楚,2种都可以选择手机类型转换贴子15L和19L有2种转换器的直下链,也免注册
tgrdyhlmkhkjyhljph=trpj=p[pp[pgjfptj
视频播放的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁(window.slotbydup=window.slotbydup || []).push({
id: '2081942',
container: s,
size: '1000,60',
display: 'inlay-fix'怎么打开arm文件?
怎么打开arm文件?
09-01-21 &映像文件的生成和运行 - ARM技术论坛 -
中国电子技术论坛 -
最好最受欢迎电子论坛!
后使用快捷导航没有帐号?
映像文件的生成和运行
20:35:02  
映像文件的生成和运行
德国罕见的科学大师莱布尼茨,在他的手迹里留下这么一句话:“1与0,一切数字的神奇渊源。这是造物的秘密美妙的典范,因为,一切无非都来自上帝。”二进制0和1两个简单的数字,构造了神奇的计算机世界,对人类的生产活动和社会活动产生了极其重要的影响,并以强大的生命力飞速发展。在嵌入式系统移植过程中,不管文件数量多么庞大的工程,经过编译工具的层层处理后,最终生成一个可以加载到存储器内执行的二进制映像文件(.bin)。本节内容将会探讨映像文件的生成过程,以及它在存储设备的不同位置对程序运行产生的影响,为本书后文嵌入式系统的移植打下坚定的基础。
1.1.1& &编译过程
GNU提供的编译工具包括汇编器as、C编译器gcc、C++编译器g++、链接器ld、二进制转换工具objcopy和反汇编的工具objdump等。它们被称作GNU编译器集合,支持多种计算机体系类型。基于ARM平台的工具分别为arm-linux-gcc、arm-linux-g++、arm-linux-ld、arm-linux-objcopy和arm-linux-objdump。arm-linux交叉编译编译工具链的制作方法已经详细介绍过,编译程序直接使用前面制作好的工具链。
交叉工具链下载地址:http://www.arm8.net/thread-36-1-1.html
GNU编译器的功能非常强大,程序可以用C文件、汇编文件编写,甚至是二者的混合。如图1. 3所示是程序编译的大体流程,源文件经过预处理器、汇编器、编译器、链接器处理后生成可执行文件,再由二进制转换工具转换为可用于烧写到Flash的二进制文件,同时为了调试的方便还可以用反汇编工具生成反汇编文件。图中双向箭头的含义是,当gcc增加一些参数时可以相互调用汇编器和链接器进行工作。例如输入命令行“gcc –O&&main.c”后,直接就得到可执行文件a.out(elf)。
程序编译大体上可以分为编译和链接两个步骤:把源文件处理成中间目标文件.o(linux)、obj(windows)的动作称为编译;把编译形成的中间目标文件以及它们所需要的库函数.a(linux) 、lib(windows)链接在一起的动作称为链接。现用一个简单的test工程来分析程序的编译流程,麻雀虽小五脏俱全,它由启动程序start.S、应用程序main.c、链接脚本test.lds和Makefile四个文件构成。test工程中的程序通过操作单板上的LED灯的状态来判定程序的运行结果,它除了用于理论研究之外,没有其它的实用价值。
1.& &编译
在编译阶段,编译器会检查程序的语法、函数与变量的声明情况等。如果检查到程序的语法有错误,编译器立即停止编译,并给出错误提示。如果程序调用的函数、变量没有声明原型,编译器只会抛出一个警告,继续编译生成中间目标文件,待到链接阶段进一步确定调用的变量、函数是否存在。
程序清单1. 1start.S中汇编代码
*& && &This is a part of the test project
*& && &Author: LiQiang Date:
*& && &Licensed under the GPL-2 or later.
.globl _start
& & #define REG32 0x
& & ldr r0, =REG32
& & orr r0, r0, #0x13
& & mcr p15,0,r0,c15,c2,4& && &
& & /*关闭看门狗*/
& & #define WATCHDOG 0x7E004000
& & ldr r0, =WATCHDOG
& & mov r1, #0
& & str r1, [r0]
clean_bss:
& & ldr r0, =bss_start
& & ldr r1, =bss_end
& & mov r3, #0
& & cmp r0, r1
& & beq clean_done
clean_loop:
& & str r3, [r0], #4
& & cmp r0, r1&&
& & bne clean_loop& && &
clean_done:
& &&&/* 初始化栈 S3C6410 8K的SRAM映射到0地址处*/
& &&&ldr sp, =8*1024
& &&&bl main
& & b halt&&
start.S文件的内容如程序清单1. 1,文件中的_start函数为C语言运行环境做最低限度的初始化:将S3C6410处理外设端口的地址范围告知ARM内核,关闭看门狗,清除bss段,初始化栈。初始化工作完毕后,跳转到main()。start.S是用汇编语言编写的代码文件,文件中定义了一个WATCHDOG宏,用于寄存器的赋值。在汇编文件中出现#define宏定义语句,对于初学者可能会有些迷惑。
事实上,汇编文件有“.S”和“.s”两种后缀,在以“.s”为后缀的汇编文件中,程序完全是由纯粹的汇编代码编写。所谓的纯粹是相对以“.S”为后缀的汇编文件而言的,由于现代汇编工具引入了预处理的概念,允许在汇编代码(.S)中使用预处理命令。预处理命令以符号“#”开头,包括宏定义、文件包含和条件编译。在U-Boot和Linux内核源码中,这种编程方式运用非常广泛
程序清单1. 2&&main.c文件内容
*&&This is a part of the test project
* Author: LiQiang Date:
* Licensed under the GPL-2 or later.
#define GPMCON&&*((volatile unsigned long*)0x7F008820)
#define GPMDAT&&*((volatile unsigned long*)0x7F008824)
#define GPMPUD&&*((volatile unsigned long*)0x7F008828)
int main()
& & static int flag = 12;
& & GPMCON = 0x1111; /* 输出模式 */
& & GPMPUD = 0x55;& &/* 使能下拉 */
& & GPMDAT = 0x0f;& &/* 关闭LED */
& & if(12 == flag)
& && &&&GPMDAT = 0x00;
& && &&&GPMDAT = 0x0f;
& & while(1);
& & return 0;
main.c文件内容如程序清单1. 2所示,main.c中的main函数是运行完_start函数的跳转点。main()中首先定义了一个静态局部变量初值为12,然后配置S3C6410处理器的GPM端口为输出、下拉模式,并将GPM低四位管脚的设为高电平(单板上LED在管脚为高电平的熄灭)。最后判断是flag是否等于12,如果等于点亮LED,否则不点亮。从程序上看,这个判断语句好像多此一举、莫名其妙,因为flag期间并没有作任何改变。其实,这个变量是为讲解程序的运行地址和加载地址的概念而定义的,它与程序运行的位置有关。
将上面两个源码文件处理成中间目标文件,分别输入如下命令行:
arm-linux-gcc -o mian.o main.c –c
arm-linux-gcc -o start.o start.S –c
得到main.o&&Start.o两个中间目标文件,供链接器使用。
2.& &链接
链接是汇编阶段生成的中间目标文件,相互查找自己所需要的函数与变量,重定向数据,完成符号解析的过程。包括对所有目标文件进行重定位、建立符号引用规则,同时为变量、函数等分配运行地地址。函数与变量可能来源与其它中间文件或者库文件,如果没有找到所需的实现,链接器立即停止链接,给处错误提示。
利用一个链接脚本(.lds后缀)来指导链接链接器工作。控制输出节在映像文件中的布局。fortest.lds是一个简单的链接脚本,指示了程序的运行地址(又称链接地址)为0x以及text段、data段和bss段在映像文件中的空间排布顺序。fortest.lds文件的内容如下:
ENTRY(_start)
& && &&&. = 0x;
& && &&&. = ALIGN(4);
& && &&&.text : {
& && && && && & start.o (.text)
& && && && && & * (.text)
& && &&&.data : {
& && && && && & * (.data)
& && &&&bss_start = .;
& && &&&.bss : {
& && && && && & * (.bss)
& && &&&bss_end&&= .;
1)& && &&&text段代码段(text segment),通常是用来存放程序执行代码的内存区域。这块区域的大小在程序编译时就已经确定,并且内存区域通常属于只读,某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量。
2)& && &&&data段数据段(data segment),数据段是存放已经初始化不为0的静态变量的内存区域,静态变量包括全局变量和静态局部变量,它们与程序有着相同的生存期。
3)& && &&&bss段bss segment,bbs段与data段类似,也是存放的静态变量的内存区域。与data段不同的是,bbs段存放是没有初始化或者初始化为0的静态变量,并且bbs段不在生成的可执行二进制文件内。bss_start表示这块内存区域的起始地址,bss_end表示结束地址,它们由编译系统计算得到。未初始化的静态变量默认为0,因此程序开始执行的时候,在bss_start到bss_end内存中存储的数据都必须是0。
4)& && &&&其他段,上面三个段是编译系统预定义的段名,用户还能通过.section伪操作自定义段,在后面的移植过程我们会发现,Linux内核源码中为了合理地排布数据实现特定的功能,定义了各种各样的段。
在宿主机上输入以下命令行,完成中间的目标文件的链接和可执行二进制文件的格式转换。
arm-linux-ld –T test.lds -o test.elf start.o main.o
arm-linux-objcopy -O binary test.elf test.bin
arm-linux-objdump -D test.elf & test.dis
如图1. 4所示是使用arm-linux-objcopy格式转换工具得到的二进制文件test.bin的内容,这些内容是处理器能够识别的机器码,我们往往难以直接阅读、理解它们的含义。使用arm-linux-objdump工具生成便以我们阅读的反汇编文件test.dis。对比二进制文件test.bin的内容,耐心细致地分析反汇编文件,如程序清单1. 3所示,可以提炼出大量的信息。
程序清单1. 3text.dis文件内容
&_start&:&&/* 代码段起始位置程序的运行地址为0x*/
:& &e3a00207& & mov r0, # ; 0x
:& &e3800013& & orr r0, r0, #19 ; 0x13
:& &ee0f0f92& & mcr 15, 0, r0, cr15, cr2, {4}
5000000c:& &e59f0030& & ldr r0, [pc, #48]& &;
&halt+0x4&
:& &e3a01000& & mov r1, #0&&; 0x0
:& &e5801000& & str r1, [r0]
&clean_bss&: /* 清除bss段 */
:& &e59f0028& & ldr r0, [pc, #40]& &;
&halt+0x8&
5000001c:& &e59f1028& & ldr r1, [pc, #40]& &; 5000004c &halt+0xc&
:& &e3a03000& & mov r3, #0&&; 0x0
:& &e1500001& & cmp r0, r1
:& &0a000002& & beq
&clean_done&
5000002c &clean_loop&:
5000002c:& &e4803004& & str r3, [r0], #4
:& &e1500001& & cmp r0, r1
:& &1afffffc& & bne 5000002c &clean_loop&
&clean_done&:
:& &e3a0da02& & mov sp, #8192& &; 0x2000 /* 初始化sp */
5000003c:& &eb000003& & bl&& &main& /* 跳转至mian() */
:& &eafffffe& & b& & &halt&
:& &7e004000& & .word& &0x7e004000
:& && & .word& &0x
5000004c:& && & .word& &0x
&main&: /* main()*/
:& &e52db004& & push& & {fp}& && &&&; (str fp, [sp, #-4]!)
:& &e28db000& & add fp, sp, #0&&; 0x0
:& &e3a0247f& & mov r2, # ; 0x7f000000
5000005c:& &e2822b22& & add r2, r2, #34816&&; 0x8800
:& &e2822020& & add r2, r2, #32 ; 0x20
:& &e3a03c11& & mov r3, #4352& &; 0x1100
:& &e2833011& & add r3, r3, #17 ; 0x11
5000006c:& &e5823000& & str r3, [r2]&&/*&&GPMCON = 0x1111 */
:& &e3a0347f& & mov r3, # ; 0x7f000000
:& &e2833b22& & add r3, r3, #34816&&; 0x8800
:& &e2833028& & add r3, r3, #40 ; 0x28
5000007c:& &e3a02055& & mov r2, #85 ; 0x55
:& &e5832000& & str r2, [r3]&&/*&&GPMPUD = 0x55 */
:& &e3a0347f& & mov r3, # ; 0x7f000000
:& &e2833b22& & add r3, r3, #34816&&; 0x8800
5000008c:& &e2833024& & add r3, r3, #36 ; 0x24
:& &e3a0200f& & mov r2, #15 ; 0xf
:& &e5832000& & str r2, [r3]&&/* GPMDAT = 0x0f */
:& &e59f3038& & ldr r3, [pc, #56]& &;
&main+0x88&&&/* 读取flag变量存储地址 */
5000009c:& &e5933000& & ldr r3, [r3]/* 读取flag变量的值 */
:& &e353000c& & cmp r3, #12 ; 0xc
:& &1a000005& & bne
&main+0x70&
:& &e3a0347f& & mov r3, # ; 0x7f000000
500000ac:& &e2833b22& & add r3, r3, #34816&&; 0x8800
:& &e2833024& & add r3, r3, #36 ; 0x24
:& &e3a02000& & mov r2, #0&&; 0x0
:& &e5832000& & str r2, [r3]
500000bc:& &ea000004& & b& & &main+0x84&
:& &e3a0347f& & mov r3, # ; 0x7f000000
:& &e2833b22& & add r3, r3, #34816&&; 0x8800
:& &e2833024& & add r3, r3, #36 ; 0x24
500000cc:& &e3a0200f& & mov r2, #15 ; 0xf
:& &e5832000& & str r2, [r3]
:& &eafffffe& & b& & &main+0x84&
:& &500000dc& & .word& &0x500000dc
Disassembly of section .data:
500000dc &flag.1245&: /* flag变量的地址为0x5000_00dc,值为12 */
500000dc:& &0000000c& & .word& &0x0000000c
从test.dis反汇编文件中可知,test.bin包含了代码段和数据段,并没有包含bss段。我们知道,bbs内存区域的数据初始值全部为零,区域的起始位置和结束位置在程序编译的时候预知。很容易想到在程序开始运行时,执行一小段代码将这个区域的数据全部清零即可,没必要在test.bin包含全为0的bss段。编译器的这种机制有效地减小了镜像文件的大小、节约了磁盘容量。
main()函数的核心功能是验证flag变量是否等于12,现在追踪下这个操作的实现过程。要想读取flag的值,必须知道它的存储位置,首先执行指令“ldrr3, [pc, #56]”得到flag变量的地址(指针)。pc与56相加合成一个地址,它是相对pc偏移56产生的。pc+56地址处存放了flag变量的指针0x5000_00dc,读取出来存放到r3寄存器。然后执行指令“ldrr3, [r3]”将内存0x5000_00dc地址处的值读出,这个值就是flag,并覆盖r3寄存器。最后,判断r3寄存器是否等于12。flag变量的地址在链接阶段已经被分配好了,固定在0x5000_00dc处,但是从代码中,我们没有找到对flag变量赋初值的语句,尽管在main函数已经用C语句“flag = 12”对它赋初值。
现提供一个验证程序效果的简单方法:将S3C6410处理器设置为SD卡启动方式,使用SD_Writer软件将test.bin烧写至SD卡中,然后将SD卡插入单板的卡槽,复位启动即可。实际上,启动的时候test.bin被加载到内部SRAM中,SRAM映射到0地址处。这个简单方法可以用来验证一些裸板程序,方法实现的原理和SD_Writer软件用法现在不展开讨论,目前只要会使用即可。复位后,LED并没有点亮。
如果每次编译都要重复输入编译命令,操作起来很麻烦,为此test工程中建立了一个Makefile文件,内容如下:
test.bin: start.o main.o
& & arm-linux-ld -T fortest.lds -o test.elf start.o main.o
& & arm-linux-objcopy -O binary test.elf test.bin
& & arm-linux-objdump -D test.elf & test.dis
start.o : start.S
& & arm-linux-gcc -o start.o start.S -c
main.o : main.c
& & arm-linux-gcc -o main.o main.c -c
& & rm *.o test.*
当将链接脚本中的运行地址修改为0时,进入test目录,输入“make clean”命令清除旧的文件,再输入“make”重新编译程序,验证新生成的test.bin文件的效果,发现LED全部点亮,产生这个现象的原因在下一个小节讲述。
1.1.1& &代码搬运
当程序执行时,必须把代码搬运到链接时所指定的运行地址空间,以保证程序在执行过程中对变量、函数等符号的正确引用。在带有操作系统中,这个过程由操作系统负责完成。而在裸机环境下,镜像文件的运行地址由程序员根据具体平台指定,加载地址又与处理器的设计密切相关。通常情况下,启动代码最先执行一段位置无关码,这段代码实现程序从加载地址到运行地址的重定位,或者将程序从外部存储介质直接拷贝至其运行地址。
1.& &位置无关码
位置无关码必须具有位置无关的跳转、位置无关的常量访问等特点,不能访问静态变量,都是相对pc的偏移量来函数的跳转或者常量的访问。在ARM 体系中,使用相对跳转指令b/bl实现程序跳转。指令中所跳转的目标地址用基于当前PC的偏移量来表示,与链接时分配给地址标号的绝对地址值无关,因而代码可以在任何位置正确的跳转,实现位置无关性。
使用ldr伪指令将一个常量读取到非pc的其他通用寄存器中,可实现位置无关的常量访问。例如:
ldr r0, =WATCHDOG
如果使用ldr伪指令将一个函数标号读取到pc,这是一条与位置有关的跳转指令,执行的结果是跳转到函数的运行地址处。
2.& &运行地址与加载地址
试想一下,当系统上电复位的时候,如果test.bin刚好位于在0x地址(flag的初值12位于0x5000_00dc),PC指向0x地址,那么这段代码按照上述flag变量的读取步骤,能够准确无误的得到结果。但是,如果test.bin位于0地址(flag的初值12位于0xdc,LED不亮时的情况),PC指向0地址,程序依然从0x5000_00dc地址读取flag变量,实际上它的初值位于0xdc。这时从C语言的角度看,出现一个flag不等于它的初值的现象(期间没有改变flag)。出现错误的原因是在程序中使用了位置相关的变量,但运行地址与加载地址不一致(加载地址为0,运行地址为0x)。由此,能够容易理解运行地址和加载地址的含义:
加载地址是系统上电启动时,程序被加载到可直接执行的存储器的地址,也就是程序在RAM或者Flash ROM中的地址。因为有些存储介质只能用来存储数据不能执行程序,例如SD卡和NAND Flash等,必须把程序从这些存储介质加载到可以执行的地址处。运行地址就是程序在链接时候确定的地址,比如fortest.lds链接脚本指定了程序的运行地址为0x,那么链接器在为变量、函数等分配地址的时候就会以0x作为参考。当加载地址和运行地址不相等时,必须使用与位置无关码把程序代码从它的加载地址搬运至运行地址,然后使用“ldr pc, =label”指令跳转到运行地址处执行。
1.1.2& &混合编程
在嵌入式系统底层编程中,C语言和汇编两种编程语言的使用最广泛。C语言开发的程序具有可读性高,容易修改、移植和开发周期短等特点。但是,C语言在一些场合很难或无法实现特定的功能:底层程序需要直接与CPU内核打交道,一些特殊的指令在C语言中并没有对应的成分,例如关闭看门狗、中断的使能等;被系统频繁调用的代码段,对代码的执行效率要求严格的时候。事实上,CPU体系结构并不一致,没有对内部寄存器操作的通用指令。汇编语言与CPU的类型密切相关,提供的助记符指令能够方便直接地访问硬件,但要求开发人员对CPU的体系结构十分熟悉。在早期的微处理器中,由于处理器速度、存储空间等硬件条件的限制,开发人员不得不选用汇编语言开发程序。随着微处理器的发展,这些问题已经得到很好的解决。如果依然完全使用汇编语言编写程序,工作量会非常大,系统很难维护升级。大多数情况下,充分结合两种语言的特点,彼此相互调用,以约定规则传递参数,共享数据。
1.& &汇编函数与C语言函数相互调用
C程序函数与汇编函数相互调用时必须严格遵循ATPCS(ARMThumb Procedure Call Standard)。函数间约定R0、R1和R2为传入参数,函数的返回值放在R0中。GNU ARM编译环境中,在汇编程序中要使用.global伪操作声明改汇编程序为全局的函数,可被外部函数调用。在C程序中要被汇编程序调用的C函数,同样需要用关键字extern声明。
程序清单1. 4代码重定位函数
.globl&&relocate_code
relocate_code:
& & mov r4, r0&&/* save addr_sp */
& & mov r5, r1&&/* save addr of gd */
& & mov r6, r2&&/* save addr of destination */
& & /* Set up the stack */
stack_setup:
& & mov sp, r4
& & adr r0, _start
& & cmp r0, r6
& & beq clear_bss& && & /* skip relocation */
& & mov r1, r6& && && & /* r1 &- scratch for copy_loop */
& & ldr r3, _bss_start_ofs
& & add r2, r0, r3& && &/* r2 &- source end address& &&&*/
程序清单1. 4是从arch\arm\cpu\arm1176\start.S文件(U-Boot)中截取的代码片段,relocate_code函数用于重定位代码。它在C程序中,通过relocate_code(addr_sp, id, addr)被调用。变量addr_sp、id和addr分别通过寄存器R0、R1和R3传递给汇编程序,实现了C函数和汇编函数数据的共享。
2.& &C语言内嵌汇编
当需要在C语言程序中内嵌汇编代码时,可以使用gcc提供的asm语句功能。
程序清单1. 5整数原子加操作的实现
* ARMv6 UP and SMP safe atomic ops.&&We use load exclusive and
* store exclusive to ensure that these are atomic.&&We may loop
* to ensure that the update happens.
static inline void atomic_add(int i, atomic_t *v)
& & __asm__ __volatile__(&@ atomic_add\n&
&1: ldrex& &%0, [%3]\n&
&& &add %0, %0, %4\n&
&& &strex& &%1, %0, [%3]\n&
&& &teq %1, #0\n&
&& &bne 1b&
& & : &=&r& (result), &=&r& (tmp), &+Qo& (v-&counter)
& & : &r& (&v-&counter), &Ir& (i)
& & : &cc&);
程序清单1. 5是从Linux源码文件arch/arm/include/asm/atomic.h截取的一段代码,本节内容不分析函数的具体实现。对于初学者,这段代码看起来晦涩难懂,因为这不是标准C所定义的形式,而是gcc对C语言扩充的asm功能语句,用以在C语言程序中嵌入汇编代码。asm语句最常用的格式为:
__asm __&&__volatile__(“ inst1 op1, op2, . \n”
“ inst2 op1, op2, . \n”& && && &/* 指令部分必选*/
“ instN op1, op2, . \n”
: output_operands& &/* 输出操作数可选 */
: input_operands& && &&&/* 输入操作数可选 */
: clobbered_operands& & /* 损坏描述部分可选*/
它由四个部分组成:指令部分,输出部分,输入部分,损坏描述部分。各部分使用“:”格开,指令部分必不可少,其他三部分可选,但是如果使用了后面的部分,而前面部分为空,也需要用“:”分隔,相应部分内容为空。__asm__表示汇编语句的起始,__volatile__是一个可选项,加上它可以防止编译器优化时对汇编语句删除、移动。
指令部分,指令之间使用“\n”(也可以使用“;”或者“\n\t”)分隔。嵌入汇编指令的格式与标准汇编指令的格式大体相同,嵌入汇编指令的操作数使用占位符“%”预留位置,用以引用C语言程序中的变量。操作数占位符的数量取决于CPU中通用寄存器的总数量,占位符的格式为%0,%1,……,%n。
输出、输入部分,这两部分用于描述操作数,不同的操作数描述语句之间用逗号分隔,每个操作数描述符由限定字符串和C语言表达式组成,当限定字符串中带有“=”时表示该操作数为输出操作数。限定字符串用于指示编译器如何处理C语言表达式与指令操作数之间的关系,限定字符串中的限定字母有很多种,有些是通用的,有些跟特定的体系相关。在程序清单1. 5中:result、tmp和v-&counter是输出操作数,分别赋给%0、%1和%2;v-&counter和i是输入操作数,分别赋给%3和%4。其中,“r”:表示把变量放入通用寄存器中;“I”:表示0-31之间的常数。
站长推荐 /5
Powered by

我要回帖

更多关于 mp4格式电影无法播放 的文章

 

随机推荐