一灯大师:一点就是好几年

 

1.几条汇编指令

  1. LDR :(load)读内存

      LDR   R0 , [R1]                       // 假设R1的值是x,读取地址x上的数据,保存到R0中。

2. STR :(store)写内存

      STR   R0 , [R1]                      // 假设R1的值是x,把R0的值写到地址x上。

3. B:跳转

      halt:  b  halt                     // 此例用于实现死循环功能,避免程序跑飞。

4. MOV :(move)(移动) 赋值

      LDR   R0 , R1                        // 把R1的值赋给R0,R0 = R1。

      LDR   R0 , #0x01                   // 把立即数的值赋给R0,R0 = 0x01。

5. LDR :伪指令用法

      LDR   R0 ,= 0x12345678      // 把 0x12345678 这个值赋给R0,R0 = 0x12345678。

      伪指令会被拆分为几条真正的arm指令执行,引入伪指令是因为使用MOV指令赋值时真正值得小于寄存位宽。

 

2.汇编代码


.text
.global _start 
_start:
    
    /*配置GPF4为输出引脚*/
    /*把0x100写到地址0x56000050*/
	LDR r0,=0x56000050
	LDR r1,=0x100    /* mov R0,#0X100 */
	str r1,[r0]

    /*设置GPF4为输出高电平*/
    /*把0写到地址0x56000054*/
	LDR r0,=0x56000054
	LDR r1,=0x00    /* mov R0,#0X00 */
	str r1,[r0]
    
    /* 死循环 */
mainloop:
	b mainloop

.text和.global 是arm-gcc编译器的关键词。

.text 段保存代码,是只读和【可执行】的,后面那些指令都属于【.text段。
.global 告诉编译器后续跟的是一个全局可见的名字【可能是变量,也可以是函数名】;
在本例中,_start是一个函数的起始地址,也是编译、链接后程序的【起始地址】。由于程序是通过加载器来加载的,必须要找到 _start 名字的函数,因此_start必须定义成全局的,以便存在于编译后的全局符合表中,供其它程序【如加载器】寻找到。

 

3.Makefile

led.bin:led.s
	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 -f *.bin  *.o *.elf

 

4.反汇编结果

可见其中的地址、机器码和汇编码。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值