第1个ARM裸板程序及引申(第004节_汇编与机器码)【修改机器码点亮led2]

汇编代码如下,点亮 jz2440 LED1 灯 

 
 
/*
 * 点亮LED2: gpf5
 */
 
.text
.global _start
 
_start:
 
/* 配置GPF5为输出引脚
 * 把0x400写到地址0x56000050
 */
	ldr r1, =0x56000050
	ldr r0, =0x100	/* mov r0, #0x400 */
	str r0, [r1]
 
 
/* 设置GPF5输出高电平 
 * 把0写到地址0x56000054
 */
	ldr r1, =0x56000054
	ldr r0, =0	/* mov r0, #0 */
	str r0, [r1]
 
	/* 死循环  while(true) 相当于  */
halt:
	b halt
 

反汇编以后的代码: 上面代码存在伪指令 伪指令转化为在真正 汇编指令 

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

最终生成的: led.on.dis

led_on.elf:     file format elf32-littlearm

Disassembly of section .text:

伪指令转化为在真正 汇编指令 

地址:可以理解为序号,地址在sram定义真正的 
地址  机器码   汇编码   

00000000 <_start>:
   0: e59f1014  ldr r1, [pc, #20] ; 1c <halt+0x4>
   4: e3a00c01 	mov	r0, #256	; 0x100
   8: e5810000  str r0, [r1]
   c: e59f100c  ldr r1, [pc, #12] ; 20 <halt+0x8>
  10: e3a00000  mov r0, #0  ; 0x0
  14: e5810000  str r0, [r1]

00000018 <halt>:
  18: eafffffe  b 18 <halt>
  1c: 56000050  .word 0x56000050
  20: 56000054  .word 0x56000054
Disassembly of section .ARM.attributes:

00000000 <.ARM.attributes>:
   0: 00001741  andeq r1, r0, r1, asr #14
   4: 61656100  cmnvs r5, r0, lsl #2
   8: 01006962  tsteq r0, r2, ror #18
   c: 0000000d  andeq r0, r0, sp
  10: 00543405  subseq  r3, r4, r5, lsl #8
  14: 01080206  tsteq r8, r6, lsl #4 

地址是nand上的地址   ,cpu 从0地址上读取依次读取机器码,会把所有的机器码loading到内存里面去, 程序运行内存上的机器码

上面代码解读 :

arm 有32个寄存器, r0-r16, 
pc  : 程序指针   当前地址 +8  , 为什么, pc = 当期地址+8 , 在执行0时候,已经在解析4,读取8在    [这个叫做 汇编的流水线] 

pc : 程序寄存器, 当前程序执行在哪里, 所以只有一个,一个国家只有一个皇帝 , pc 指向那条指令, cpu执行哪条 , 程序跑飞了, pc寄存器内容不对了
sp  : 栈指针
lr  : 包含返回地址, 函数执行完毕要回到原来地方,原来地方就是保持在lr里面 

arm 内部的寄存器 + 别名

解析第一条指令 :  0: e59f1014 ldr r1, [pc, #20] ; 1c <halt+0x4>   (这就是伪指令的实际汇编)

当前指令地址是0 , pc =  0 + 8 +  20  =  0x1c  去0x1c 读取该地址的值56000050    写入 r1
 1c:  56000050  .word 0x56000050

0:表示当前地址  8可以理解为流水 执行当前执行,实际读取往后读取到8地址, 20就是#20

【这里可以这么理解: pc首先指向0,执行该指令, 然后执行0x1c读取寄存器  pc指了2个方法】

第二条: mov  r0, #5376 ; 0x1500   把 0x1500 写入 r0 【pc继续往下走,执行第二条】

第三条:    e5810000  str r0, [r1]  把 r0 0x1500 写入到 r1 对应内存 

第四条:      c:  e59f100c  ldr r1, [pc, #12] ; 20 <halt+0x8>
     
    0xc 【当前指令的地址】+ 8 + 20 = 0x20  去0x20地址读取它的值0x056000054存放到 r1中   r1=0x56000054(cpu把寄存器单做内存来使用)

.....

编译器 把 伪指令转化为在真正 汇编指令 
把汇编指令转化为机器码, led.bin内部就是机器码
机器码就是可以烧写到裸机上
汇编码、C都是给程序员一样看的,机器码给机器跑的

在上面基础上要实现功能: 

练习: 在 原来编译的 led_on.S  修改 机器码, 点亮 LED2
那么需要去修改机器码, 如何修改机器码 , 就要知道 上面的第二条 mov 指令  

                                     这内部是如何转化的 汇编码和机器码
  4:  e3a00c15  mov   《============》  r0, #5376 ; 0x1500 

看芯片手册: ARM Architecture Reference Manual 找到mov 指令

 上图解读: 

bit[23-20] 1010 表示mov指令
bit[15-12] 0000 表示r0
bit[11-0]  表示0x100   
修改机器码, mov r0,#0x400 那么就可以点亮led2了, 如果是汇编,那么如何修改机器码直接

bit[11-0] 12位如何表示 0x100 研究?  

分析 :

整个12 位: 高4位 (rotate) +  低8位 (immed_8) = 12 

立即数 
   低8位运算: 
   高4位运算:

例子: 
0x100   二进制 0001 00000000    立即数 1100 0000 0001  如何运算来的

如何运算得到立即数的: 
一共32位,1要通过右移编程   ... 0001   ,1 右移24位 
ratate = 24/2  = 12    1100   所以立即数就是: 1100 0000 0001

同理要点亮led2:  
0x400  而进制 0100 00000000  

低8位:  1左移动22位  ---- 0000 0001  
高8位:  22/2= 1    ----  1011
立即数: 1011 0000 0001   

用UE打开led.bin,修改地址 e3a00c01   为 e3a00cb1烧进去 ,那么就可以点亮led2了

 0x100是不是 1循环右移 24位 ?   这里以32位为准, 

00000....000000000000000(23个0)1  右移动24位就是    00-00(23位)100000000(8个0) 23+1+8=32 

 那么我们把 : 

12位:  高4位  (rotate,移位数) +  低8位 (immed_8 立即数,循环右移动2*rotate位)

                                            rotate = 12   immed_8 =  1

-比如: 0x100   立即数:   1100  00000001
 如果我们要点亮第二个LED灯:  此时 ldr r0, =0x400    /* mov r0, #0x400 */

0x400    1右移动 22位     0000...00(21个0)10000....0(10个0)

rotate  = 22/2=11  1011
immed_8 = 1        0000 0001 

修改: bit[11-0]  其他的不变, 在LED的基础上

 修改led.bin

刷进去点亮的是led2 

资源地址:修改机器码点亮led2-资料2021-11-21.zip-Unix文档类资源-CSDN下载

              

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值