嵌入式linux------汇编码和机器码

使用点亮LED的简单程序分析其汇编码和机器码,通过直接修改bin文件中的机器码修改功能,点亮其他的LED灯。

首先修改Makefile文件把elf文件反汇编生成dis文件,查看其真正的汇编指令:

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>:
/*[第1行]*/   0:	e59f1014 	ldr	r1, [pc, #20]	; 1c <.text+0x1c>
/*[第2行]*/   4:	e3a00c01 	mov	r0, #256	; 0x100
/*[第3行]*/   8:	e5810000 	str	r0, [r1]
/*[第4行]*/   c:	e59f100c 	ldr	r1, [pc, #12]	; 20 <.text+0x20>
/*[第5行]*/  10:	e3a00000 	mov	r0, #0	; 0x0
/*[第6行]*/  14:	e5810000 	str	r0, [r1]

00000018 <halt>:
  18:	eafffffe 	b	18 <halt>
  1c:	56000050 	undefined
  20:	56000054 	undefined

在汇编指令中,最右边是汇编码,中间是机器码,最左边是地址。

                                                                

在cpu中有27个寄存器,其中16个可以使用,如上图所示,最右边一列是寄存器的别名。其中pc为Program counter程序计数器,当把一个地址写入此寄存器中时,程序就跳到此地址中去。lr是link register链接寄存器,用来保存返回地址,当程序执行完后调回到这个地址。sp是stack point栈指针寄存器。

程序解析过程说明:

/*[第1行]*/   0:    e59f1014     ldr    r1, [pc, #20]    ; 1c <.text+0x1c> 在这一行程序中,当前指令地址为0,pc为当前指令地址加8,所以r1 = 0 + 8 + 20 = 28 = 0x1c,但是为什么是加8?因为在ARM系统中cpu是以流水线(ARM内核使得执行效率更加高)的方式进行工作的,即当前执行地址A的指令,那么cpu已经在对地址A+4的指令进行译码,同时已经在读取地址A+8的指令,这里A+8就是pc的值。所以在下边已经给出了0x1c地址的值就是56000050,赋给r1。

/*[第2行]*/   4:    e3a00c01     mov    r0, #256    ; 0x100  在这一行中,mov指令将立即数0x100赋给r0

/*[第3行]*/   8:    e5810000     str    r0, [r1]   在这一行将0x100写入r1对应的内存
/*[第4行]*/   c:    e59f100c     ldr    r1, [pc, #12]    ; 20 <.text+0x20> 在这一行中pc等于当前地址加8,所以r1=pc + 12 = 0xc + 8 + 12 =32=0x20,所以下边已经给出此地址的值为56000054,读取出来赋给r1。
/*[第5行]*/  10:    e3a00000     mov    r0, #0    ; 0x0 在这一行中将立即数赋给r0。
/*[第6行]*/  14:    e5810000     str    r0, [r1] 在这一行将0写入r1对应的内存

编译器将汇编码转换为机器码,这个机器码就是bin文件的内容。如果想将点亮的第一个LED灯换成第二个,经过查阅手册将GPFCON赋值改为0x400,可以通过修改汇编程序然后编译链接,但是也可以通过修改机器码来实现,就是修改第二行的MOV指令对应的机器码,首先查阅MOV指令机器码存储结构。

                              

e3a00c01     mov    r0, #256

e3a00c01的位: 

bit15~bit12用来表示r0,bit11~bit0用来表示赋值的数值立即数。其中bit11~bit8表示高四位rotate,剩下的是低8位immed_8。而立即数 = immed_8循环右移(2 * rotate)位。

根据上图rotate是12,所以是1循环右移24位得到0..(23)..100000000也就是立即数0x100

但是如果是立即数是0x400,怎么使用rotate和immed_8表示呢,将0x400展开是0..(21)..100 0000 0000数一下0的个数可知道是1循环右移22位得到,所以ratate=22/2=11,rotate为0b1011,所以12位立即数为1011 0000 0001,所以直接修改机器码e3a00c01为e3a00b01即可解决问题。

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值