ARM中的汇编和机器码

发布者:boyhxz最新更新时间:2021-10-14 来源: eefocus关键字:ARM中  汇编  机器码 手机看文章 扫描二维码
随时随地手机看文章

我们以S3C2440的GPIO汇编代码为例:


.text

.global _start

_start:

//把0x100写到地址0x56000050上,配置gpf4为输出引脚,

    ldr r1, =0x56000050

ldr r0,=0x100

str r0,[r1]

//把0x00写到地址0x56000054上,设置gpf4输出低电平, 

    ldr r1, =0x56000054

ldr r0,=0x00

str r0,[r1]

//死循环

halt:

    b halt

在上面的代码中,我们使用了伪指令ldr把值存放到r0,r1寄存器里面,所谓伪指令就是假的指令,它并不是真正的ARM指令,我们通过对elf文件进行反汇编看一下伪指令ldr对应哪些真正的汇编指令,我们修改下我们之前用的makefile文件对elf文件进行反汇编,修改后的makefile内容如下:


all:

arm-linux-gcc -c -o led_on.o led_on.S

arm-linux-ld -Ttext 0 led_on.o -o led_on.elf

arm-linux-objcopy -O binary -S  led_on.elf led_on.bin

arm-linux-objdump -D led_on.elf  > led_on.dis

clean:

rm *.bin  *.o  *.elf

反汇编之后得到的dis文件如下:


 

led_on.elf:     file format elf32-littlearm

 

Disassembly of section .text:

 

00000000 <_start>:

   0: e59f1014 ldr r1, [pc, #20] ; 1c <.text+0x1c>

   4: e3a00c01 mov r0, #256 ; 0x100

   8: e5810000 str r0, [r1]

   c: e59f100c ldr r1, [pc, #12] ; 20 <.text+0x20>

  10: e3a00000 mov r0, #0 ; 0x0

  14: e5810000 str r0, [r1]

 

00000018 :

  18: eafffffe b 18

  1c: 56000050 undefined

  20: 56000054 undefined

ldr r1, =0x56000050被转换成了ldr    r1, [pc, #20],从内存中读取值,把1c地址对应的值56000050存放到r1里面。


ldr r0,=0x100 直接被转换成了mov指令。


ldr r1, =0x56000054被转换成了ldr    r1, [pc, #12]    ; 20 <.text+0x20>,把20地址对应的值56000054存放到r1里面。


上面最左边的0 4 8这一列代表地址,第二列代表机器码,第三列代表汇编码。


我们之前说s3c2440里面有cpu,cpu里面一共更有r0-r15一共16个寄存器,这里我们使用pc值表示寄存器。我们看如下表格

左边是R0-R15,右边a1,a2....是它的别名。


pc是指program counter程序计数器,当你把一个地址写到PC寄存器的时候,程序就会跳到那个地址去,pc的值是当前指令的地址加上8,为什么要加上8,是因为ARM系统里面CPU是以流水线的方式去执行的,流水线只是当前执行地址A的指令,那么已经在对地址A+4的指令进行译码,已经在读取地址A+8的指令,这个A+8就是PC的值。 


lr是link register,用来保存返回地址,我们使用函数调用的时候,执行完这个函数要跳回原来的地方,这个原来的地方就保存在这个lr寄存器里面。


sp是stack pointer,栈指针。


我们再看前面反汇编生成的代码,第一行, 


0:    e59f1014     ldr    r1, [pc, #20]    ; 1c <.text+0x1c>

r1等于PC+20,当前指令是0,PC 是当前指令的地址加上8也就是8,那么r1=8+20=28=0x1c,然后去0x1c这个地址去读取内存的值0x56000050写入到r1里面。


另外我们看到反汇编生成的文件的第二列是机器码,也就是bin文件里面的内容,但是我们用notpad++打开led_on.bin之后发现并不是e5 9f 10 14这种,这是因为notpad++这个软件的插件有问题,我们用ultraedit软件打开bin文件之后就好了。


下面我们修改程序,点亮LED2,


方法1:修改之前的汇编代码点亮LED2


我们打开芯片手册,搜索GPFCON,发现只要把0x400写到GPFCON寄存器就可以把gpf5设置为输出引脚了,


.text

.global _start

_start:

//把0x400写到地址0x56000050上,配置gpf5为输出引脚,

    ldr r1, =0x56000050

ldr r0,=0x400

str r0,[r1]

//把0x00写到地址0x56000054上,设置gpf5输出低电平, 

    ldr r1, =0x56000054

ldr r0,=0x00

str r0,[r1]

//死循环

halt:

    b halt

然后我们重新编译即可。


方法二:直接修改之前控制LED时的led_on.bin,点亮LED2。


led_on.elf:     file format elf32-littlearm

 

Disassembly of section .text:

 

00000000 <_start>:

   0: e59f1014 ldr r1, [pc, #20] ; 1c <.text+0x1c>

   4: e3a00c01 mov r0, #256 ; 0x100

   8: e5810000 str r0, [r1]

   c: e59f100c ldr r1, [pc, #12] ; 20 <.text+0x20>

  10: e3a00000 mov r0, #0 ; 0x0

  14: e5810000 str r0, [r1]

 

00000018 :

  18: eafffffe b 18

  1c: 56000050 undefined

  20: 56000054 undefined


我们只要把上面mov    r0, #256    ; 0x100  对应的机器码e3a00c01修改为mov    r0, #1024    ; 0x400对应的机器码就可以了,那么我们要知道机器码e3a00c01里面哪一部分对应的是0x100,然后修改成0x400就可以了,那么我们看一下MOV指令对应的机器码的格式,

mov    r0, #256    ; 0x100的时候对应的机器码是e3a00c01=1110,0011,1010,0000,0000,1100,0000,0001。


前面bit24-21是1101用来表示MOV指令,bit15-12是0000表示r0,后面的bit11-0就用来表示0x100. 那么我们只需要修改低12位就可以表示mov    r0, #1024。


那么低12位怎么表示一个立即数呢,这12位拆分成高四位和低八位。,表示方式如下:

我们看一下0x100对应的机器码的低12位是1100,0000,0001,也就是0000,0001右移2*1100,也就是0000,0001右移24位. 


0000,0001循环右移1位成为1000,0000,0000,0000,0000,0000,0000,0000


然后再循环右移23位成为0000,0000,0000,0000,0000,0001,0000,0000=0x100. 


那么0x400=0000,0000,0000,0000,0000,0100,0000,0000,那么它可以由0000,0001右移22位得到。那么可以得到0x400对应的rotate=22/2=11=1011,


那么可以得到0x400对应的机器码的12位是1011,0000,0001,


那么由mov    r0, #256    ; 0x100的时候对应的机器码是e3a00c01=1110,0011,1010,0000,0000,1100,0000,0001。可以知道


mov    r0, #1024    ; 0x400对应的机器码是1110,0011,1010,0000,0000,1011,0000,0001=e3a00b01.


通过上面的对比可以发现,显然是直接修改汇编代码比较简单,修改机器码的方法太麻烦了。

关键字:ARM中  汇编  机器码 引用地址:ARM中的汇编和机器码

上一篇:S3C2440裸机------时钟
下一篇:S3C2440框架与启动过程

推荐阅读最新更新时间:2024-11-12 07:24

关于ARM的RO,RW,ZI
一直以来对于ARM体系中所描述的RO,RW和ZI数据存在似是而非的理解,这段时间对其仔细了解了一番,发现了一些规律,理解了一些以前书本上有的但是不理解的东西,我想应该有不少人也有和我同样的困惑,因此将我的一些关于RO,RW和ZI的理解写出来,希望能对大家有所帮助。 要了解RO,RW和ZI需要首先了解以下知识: ARM程序的组成 此处所说的 ARM程序 是指在ARM系统中正在执行的程序,而非保存在ROM中的bin映像(image)文件,这一点清注意区别。 一个ARM程序包含3部分:RO,RW和ZI RO是程序中的指令和常量 RW是程序中的已初始化变量 ZI是程序中的未初始化的变量 由以上3点说明可以理解为: RO就是readonly,
[单片机]
基于ARM的等精度测频在机组转速测控的应用
  电力系统的频率反映了发电机组发出的有功功率与负荷所需有功功率的平衡情况。高精度和高可靠性的频率测量对整个电力系统的稳定运行有着至关重要的作用,机组在开停机过程中,频率变化范围比较大,变化速度比较快,传统的测频方法由于固有的缺陷,难以很好解决这一问题。等精度测量方法的测量精度不随被测脉冲的频率高低变化而改变,只与标准计数器有关,可以使测量精度大大提高,并且闸门时间可变,可快速反应频率的变化。   1 传统测量方法的原理及误差分析   传统测量方法有2种,一种是测频法(M 法),是对被测信号在闸门时间(T—Nfo,N 个基准信号脉冲的时间)内的脉 内,对于任意的f不能保证在T时间内正好有M 个T ,因此会产生最大
[单片机]
基于<font color='red'>ARM</font>的等精度测频在机组转速测控<font color='red'>中</font>的应用
快速学Arm(11)--在C语言中内嵌汇编语言
开发Arm程序的时候,大多数时候我们使用C/C++语言就可以了,但汇编语言在某些情况下能够实现一些C语言无法实现的功能,这时候就要调用一些汇编语言的程序.我们需要大概了解一下在C语言中如何嵌入汇编语言. 1.内嵌汇编语言的语法: __asm { 指令 ...... } 2.举例:使能/禁止IRQ中断 __inline void enable_IRQ(void) { int tmp; __asm //嵌入汇编代码 { MRS tmp,CPSR //读取CPSR的值
[单片机]
汇编语言程序分析-51单片机
人工汇编出下列程序机器代码,并分析该程序段的执行功能。 CLR A MOV R2, A MOV R7, #4 LOOP: CLR C MOV A, R0 RLC A MOV R0, A MOV A, R1 RLC A MOV R1, A MOV A, R2 RLC A MOV R2, A DJNZ R7, LOOP SJMP $ ;------------------- 问题补充:问 做而论道: 为什么是把 R1的高4位,移入R2的低4位? 而不是 R2中的数,也左移4位,右边填入4个0? 还有哪儿看出来是16位数??? ;=========
[单片机]
基于MCS-51内核的汇编学习笔记
数据传送类指令: MOV 访问内部数据储存器 MOVX 访问外部数据储存器 MOVC 访问ROM储存器 XCH 整字节交换 XCHD 半字节交换(低四位) PUSH 设置堆栈指针寄存器SP所指向的内容(把字压入堆栈) POP 把字弹出堆栈; SWAP 高低字节交换指令; 数据传送指令不影响标志,只有一有堆栈操作可以直接修改程序状态字PSW,这样可以是某些标志位发生变化; 格式:MOV 操作数 目标操作数 操作数:A,Rn,direct(直接地址),@Ri(间接地址),#data; 源操作数:A,Rn,direct(直接地址),@Ri(间接地址); 提醒:MOV @DPTR,#data; 将16位的数据存入数据指针寄存器DPTR所指
[单片机]
关于在KEIL C51 嵌入汇编以及C51与A51间的相互调用
如何在 KEIL C51(v6.21) 中调用汇编函数的一个示例 有关c51调用汇编的方法已经有很多帖子讲到,但是一般只讲要点,很少有对整个过程作详细描述,对于初学者是不够的,这里笔者 通过一个简单例子对这个过程进行描述,希望能对初学者有所帮助。几年来,在这个论坛里笔者得到很多热心人指导,因此也希望 藉此尽一点绵薄之力。 在这个例子里,阐述了编写c51程序调用汇编函数的一种方法,这个外部函数的入口参数是一个字符型变量和一个位变量,返回值是 一个整型变量。例中,先用c51写出这个函数的主体,然后用SRC控制指令编译产生asm文件,进一步修改这个asm文件就得到我们所 要的汇编函数。该方法让编译器自动完成各种段的安排,提高了汇编程
[单片机]
第15章 异或与非(X86汇编教程)
一阵偷懒之后,我回来了.给你们带来了一种新的计算法则,基于二进制的.叫做异或与非(别百度了,我自己取的名字),有5个指令. 前边我们说过,电脑中,数据都是以八位二进制形式存储的(Byte,字节),某些计算自然也就用二进制进行,这里拿异或做实例吧: 异或,指令为XOR,作用是相同为0不同为1 11110010B XOR 10011111B = 01101101 如同上例,我们把2个字节进行异或,每一位对比,相同位则为0,不同的位则为1.下面是指令表: 中文称呼 指令 操作数数量 效果 异或 XOR 2 不同为1,相同为0 与
[单片机]
ARM汇编语言的程序结构
一个ARM汇编语言源程序的基本结构: AREA Init, CODE, READONLY ENTRY     Start   LDR R0, =0x3FF5000   LDR R1, 0xFF   STR R1,   LDR R0, =0x3FF5008   LDR R1, 0x01   STR R1,   ... ... ... ... ... ...   END   在 ARM( Thumb)汇编语言程序中,以程序段为单位组织代码。   段是相对独立的指令或数据序列,具有特定的名称。段可以分为代码段和数据段,代码段的内容为执行代码,数据段存放代码运行时需要用到的数据。一个汇编程序至少应该有一个代码段,当程序较长时,
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved