rockethuojian 发表于 2011-1-19 15:25:46

请教马潮老师《avr单片机嵌入式系统原理与应用实践》中的一个例子demo_5_3.asm

在157页的最下面有这样几段代码:
clr r0
ldi zl,low(led_7*2)
ldi zh,high(led_7*2)
add zl,temp
adc zh,r0
lpm

总体来说明白什么意思,就是把以z为指针寄存器的所指的内容最后放到r0,也是到z的格式是前15位表示地址,最后一位表示高字节还是低字节

但是不明白为什么能直接add zl,temp
我觉得应该temp*2 这样也把temp左移了一位 这样与zl的格式吻合 但是编译未通过 百思不得其解

希望那位牛人能指点下,非常感谢

rockethuojian 发表于 2011-1-19 23:02:02

坐等回答 谢谢

machao 发表于 2011-1-20 00:22:11

希望从汇编开始学习,值得表扬。
不过这本教材,是建立在读者学习过一门汇编语言,掌握了汇编的基本知识上的。同时整个书是以C为主,对汇编只是总结的。

至于你是否理解这段代码的意义先不说,编译不通过,说明产生了语法错误。

你是写成 add zl,temp*2 吗?这个肯定是不行的,因为没有这样的汇编指令。汇编不是C,不能随便加、减的写表示。

如果你说ldi zl,low(led_7*2)怎么可以的?

这里有两个过程:
1。low()是AVR汇编系统支持的函数,此函数将LED缓冲内存的首地址乘2,然后取低8为的值。比如得到0x05,
2。此时真正需要编译的汇编语句就是ldi zl,0x05 ,这样的汇编语句有对应的指令,所以编译不出错。

如果还是不明白,建议你先学习汇编的基本概念,比如8086的书。

rockethuojian 发表于 2011-1-20 01:08:14

回复【2楼】machao
-----------------------------------------------------------------------

谢谢您 马老师

但是感觉还是不对,我现在已经明白在编译上的问题了,但是我主要想问的是意义上的问题.

1.问题是这样的:假如说led_7的地址是0x0121然后×2(相当于左移)得到了0x0242再通过low()使得zl为0x42,然后把他和temp中的值相加(temp中的值是要显示的数字假如为3,即0x03),此时zl中的地址相当于已经是左移之后的,但是temp中的值并没有左移,所以我觉得应该也先把temp的值左移了之后再加,这样就能在lpm时用高15为正确表示地址。
2.但是我在板子上试了下,书上代码读正确;若我非得先左移(lsl temp)再相加,实验的现象反而倒是错误。所以我很想知道这段代码是怎么在道理上讲通的,即我哪里想错了。

machao 发表于 2011-1-20 01:52:50

在AVR中,ROM的地址是按字为单位的,不是字节单位。

led_7的地址是0x0121,这里是字的地址(因为led_7在ROM空间),换算成字节地址,乘上2。

而temp中的数是字节的偏移量,是按字节计算的,不需要乘2。

rockethuojian 发表于 2011-1-20 10:30:53

回复【4楼】machao
-----------------------------------------------------------------------

谢谢您 这下都明白了,问题在于我对lpm这个指令了解的不够彻底,没看清他的前15位表示的是字的地址。
而实际上可以直接把z中的地址看成flash中换算成字节的地址形式。
页: [1]
查看完整版本: 请教马潮老师《avr单片机嵌入式系统原理与应用实践》中的一个例子demo_5_3.asm