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

 /** 点亮LED2: gpf5*/.text
.global _start_start:/* 配置GPF5为输出引脚* 把0x400写到地址0x56000050*/ldr r1, =0x56000050ldr r0, =0x100  /* mov r0, #0x400 */str r0, [r1]/* 设置GPF5输出高电平 * 把0写到地址0x56000054*/ldr r1, =0x56000054ldr 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.Sarm-linux-ld -Ttext 0 led_on.o -o led_on.elfarm-linux-objcopy -O binary -S led_on.elf led_on.binarm-linux-objdump -D led_on.elf  > led.on.dis   # 反汇编
clean:rm *.bin *.o *.elf

最终生成的: led.on.dis

led_on.elf:     file format elf32-littlearmDisassembly of section .text:伪指令转化为在真正 汇编指令 地址:可以理解为序号,地址在sram定义真正的
地址  机器码   汇编码   00000000 <_start>:0: e59f1014  ldr r1, [pc, #20] ; 1c <halt+0x4>4: e3a00c01    mov r0, #256    ; 0x1008: e5810000  str r0, [r1]c: e59f100c  ldr r1, [pc, #12] ; 20 <halt+0x8>10: e3a00000  mov r0, #0  ; 0x014: e5810000  str r0, [r1]00000018 <halt>:18: eafffffe  b 18 <halt>1c: 56000050  .word 0x5600005020: 56000054  .word 0x56000054
Disassembly of section .ARM.attributes:00000000 <.ARM.attributes>:0: 00001741  andeq r1, r0, r1, asr #144: 61656100  cmnvs r5, r0, lsl #28: 01006962  tsteq r0, r2, ror #18c: 0000000d  andeq r0, r0, sp10: 00543405  subseq  r3, r4, r5, lsl #814: 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下载

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

  1. 关于在arm裸板编程时使用printf问题的解决方法

    在ARM裸板驱动编程中,是不允许程序直接调用C库程序的.为什么呢?因为此时kernel还没有被加载,所以在封装在kernel层的C库的API是用不了的,那怎么办? 在开发过程中,printf的功能我不 ...

  2. tiny4412裸板程序之点灯(一)

    最近折腾tiny4412开发板,先用裸板点个灯,玩一下裸板程序,后面打算移植最新的uboot和内核到tiny4412开发板上去. 原理图中,4个led用到的是GPM4_0 - GPM4_4. 看芯片手 ...

  3. 【嵌入式开发】LED 驱动 ( LED发光二极管原理 | 底板原理图分析 | 核心板原理图分析 | GPIO | 裸板程序烧写流程 )

    文章目录 开发板 的 LED 灯 作用 : 嵌入式软件的开发初期, 如 开发 BootLoader 代码 或者 Kernel 内核代码 过程中, 有效的调试方法有限, 此时通常使用 开发板上的 LED ...

  4. TQ210——TFTP裸板程序下载

    TQ210--TFTP裸板程序下载 1. 直接下载u-boot.bin到内存运行(使用DNW中的的210USB启动下载),在DNW中输入命令可以直接查看修改u-boot.bin 2. 通过tftp下载 ...

  5. 第0课第2节_刚接触开发板之烧写裸板程序

    第0课第2节_刚接触开发板之烧写裸板程序 tftp用法 q //退出菜单 help tftp print //显示IP set ipaddr 192.168.31.203 //设置开发板IP set ...

  6. 2021-10-18使用eop烧写裸板程序

    安装串口驱动 使用串口软件MobaXterm->点Session->找到串口->选择串口->设置波特率115200->点击Advanced Serial setting- ...

  7. 使用eop烧写裸板程序步骤

    初次使用eop烧写裸板程序步骤 1.eop连接到PC. 2.安装驱动(若安装失败,则需要禁用驱动签名即可,步骤看我之前发布的文章). 3.安装App. 4.开发板连接eop,eop连接PC. 5.执行 ...

  8. Qtcreator远程调试arm开发板程序指南

    环境配置 1 ,交叉编译gdb, 主要是gdbserver,把gdbserver 放在arm开发板的可执行程序目录里 2 安装gdb-multiarch, sudo apt-get install g ...

  9. 在riscv sifive u740开发板上运行FreeRTOS及裸板程序

    riscv是当前比较火热的玩意,sifive的u740开发板是当前性能还不错的板子. sifive官方提供了一个SDK,https://github.com/sifive/freedom-e-sdk ...

最新文章

  1. python常用模块大全总结-python常用模块整理
  2. linux命令总结之traceroute命令
  3. 一篇文章看懂Git是什么以及如何简单的上手Git
  4. [渝粤教育] 西南科技大学 动态网页设计(JSP) 在线考试复习资料
  5. java 不加锁_在java中,在高并发的时候,不加锁的时候。
  6. opencv python安装_Python 安装 第三方库的安装技巧
  7. asp.net使用httpModule来实现一个反向代理
  8. linux reboot故障
  9. Python 2和Python 3 用pip 安装时如何区分
  10. 上海怎样查询最近三年社保明细
  11. java输入两个数字和运算符_java 第二天运算符及录入函数Scanner
  12. 访问weblogic控制台报错的问题处理
  13. 数据库基础之位图索引
  14. 【排序】快排(霍尔快排)
  15. windows PCIe 工具: TeleScan
  16. 如何配置nginx,实现在手机上查看页面?
  17. zigbee 问题一:协调器究竟如何选择信道?
  18. H5 直播的疯狂点赞动画如何通过php直播平台源码实现(附完整源码)
  19. 【车位检测】基于计算机视觉实现停车场空位识别附matlab代码
  20. 微信 for BlackBerry

热门文章

  1. 远程计算机网络怎么设置,vpn错误720:不能建立到远程计算机的连接。你可能需要更改此连接的网络设置...
  2. Leetcode042接雨水039直方图最大矩形面积
  3. XFTP与XSHELL系统错误,缺少MSVCP110.DLL与MSVCR110.DLL解决办法
  4. html做万用表效果,牛人DIY高精度六位半数字万用表 - 电子制作 - 电子发烧友网...
  5. 手机游戏地图绘制软件
  6. 微信公众平台开发视频上传
  7. 【C#】RGB转CMYK
  8. windows 10安装sqlyog详细步骤
  9. 漫画 |《帝都老板十二时辰》
  10. 国际护士节活动策划PPT模板