50

asoni   2008-4-17 00:09 楼主
  KEIL C51 里怎么访问 R0-R7 寄存器? 不用汇编指令
用 sfr 定义不行
  对于一个整数除法例如:
                       unsigned int i,j,k;
                    i=j/k;
                    然后怎么得到J/K的余数呢?不重新做 J%K 的计算

回复评论 (15)

第一个问题,如果你知道当前的寄存器组的话,用绝对地址访问(...\keil\c51\inc\absacc.h)。
第二个问题,现有的C51库中没有这样的功能,如果实在需要,你可以自己用汇编语言写一个DIV_8_T div8(unsigned char i, unsigned char j)以及一个DIV_16_T div16(unsigned int i, unsigned int j),其中DIV_8_T和DIV_16_T分别为一个包含商跟余数的结构体。
点赞  2008-4-17 21:40
第一个问题,如果你知道当前的寄存器组的话,用绝对地址访问(...\keil\c51\inc\absacc.h)。
================================================================================
怎么知道当前的寄存器工作组? 以及他们的地址又是怎样的?
点赞  2008-4-17 21:59
引用: 引用 1 楼 eduhf_123 的回复:
第一个问题,如果你知道当前的寄存器组的话,用绝对地址访问(...\keil\c51\inc\absacc.h)。


向大哥学习.
原来KEIL还可以这么用

另外提出一个,既然用C,还这么去看R0-R7还用C做什么?

把C当成ASM用
那就像把CPP当C用一样,有点那个啥...

呵呵
点赞  2008-4-21 11:09
为什么不用汇编指令?
内嵌汇编更容易实现啊

当前寄存器组在PSW中的rs0、rs1决定,空间在data的最低
共4组 每组8个
0x00-0x07
0x80-0x0f
0x10-0x17
0x18-0x1f

说实话,大哥,你提的要求基本不可能做到,反正我知道的都告诉你了
点赞  2008-4-21 18:55
在C语言里,默认的寄存器组是第0组,占用内部RAM(DATA区)中0x00-0x07单元,USING N (N取0、1、2、3)或者修改PSW的语句会改变当前寄存器组,对应关系为:
第0组:0x00-0x07
第1组:0x08-0x0F
第2组:0x10-0x17
第3组:0x18-0x1F

通过absacc.h中的DBYTE宏定义来访问:
DBYTE[0x00]~DBYTE[0x1F]
点赞  2008-4-21 19:53
引用: 引用 3 楼 lbing7 的回复:
向大哥学习.
原来KEIL还可以这么用

另外提出一个,既然用C,还这么去看R0-R7还用C做什么?

把C当成ASM用
那就像把CPP当C用一样,有点那个啥...

呵呵

也没有什么了,有时间研究一下库,还是可以学到很多东西的。

在某些大工程中特别讲求效率或时序特性的部分,需要C语言来直接操纵硬件(具体方式为内嵌汇编、调用汇编函数或者访问寄存器)。

C语言可以进行底层操作不正是它精彩的地方吗?呵呵~~
点赞  2008-4-21 19:58
引用: 引用 2 楼 fycom200 的回复:
第一个问题,如果你知道当前的寄存器组的话,用绝对地址访问(...\keil\c51\inc\absacc.h)。  
================================================================================
怎么知道当前的寄存器工作组? 以及他们的地址又是怎样的?

至于如何获得当前的寄存器组,可以用如下代码实现:
[code]
如果已知要访问的Ri中的i,则可以直接这样写:
[code].
.
.
[code]
点赞  2008-4-21 20:03
向大哥学习.
原来KEIL还可以这么用

另外提出一个,既然用C,还这么去看R0-R7还用C做什么?

把C当成ASM用
那就像把CPP当C用一样,有点那个啥...

呵呵

==============================================
其实我是要解决一个问题,就是做一次除法后可以同时得到余数,这样可以大大的提高效率啊,这点在单片机中很重要
点赞  2008-4-21 22:12
学习一下。
点赞  2008-4-22 09:23
引用: 引用 6 楼 eduhf_123 的回复:

呵呵

也没有什么了,有时间研究一下库,还是可以学到很多东西的。

在某些大工程中特别讲求效率或时序特性的部分,需要C语言来直接操纵硬件(具体方式为内嵌汇编、调用汇编函数或者访问寄存器)。

C语言可以进行底层操作不正是…

引用: 引用 8 楼 fycom200 的回复:
其实我是要解决一个问题,就是做一次除法后可以同时得到余数,这样可以大大的提高效率啊,这点在单片机中很重要


赞一个...

呵呵

另外我觉得,C对底层操作的支持优势在于,它对寄存器的访问操作以及它提供的神奇的指针

这是它令人神往的地方

而不是为了小利就去破坏工具的应用本质,如果这种小利实现不到库级别的话

还有:如果编译器还有库实现不是很傻的话

我觉得这个连续的:

10 / 2
10 % 2

编译器会给出一个优化的结果
就是直接取其值

当然,我一般不用单片机做大数或是浮点的运算.
这仅仅是一个瞎想

点赞  2008-4-22 10:53
引用: 引用 10 楼 lbing7 的回复:
10 / 2  
10 % 2

编译器会给出一个优化的结果
就是直接取其值

当然,我一般不用单片机做大数或是浮点的运算.
这仅仅是一个瞎想

首先要感谢你的热情回复, 我实际看过KEIL C51生成的汇编码,这样的操作她是做了两次除法运算的,并且知道了余数就保存在R4,R5寄存器里(无符号 int 型除法),所以我打算直接把它取出来。  至于用单片机做除法运算这个是避免不了的,如果一要用到除法运算就要采取别的方案来实现那么我们还要单片机干嘛?
点赞  2008-4-22 18:30
好的编译器是会自动优化成一次除法的。
好像也可以用一句同时得到商和余数,在stdlib.h里面好像有说明,其返回值是一个结构类型,商和余数分别保存到这个结构的两个long类型的数中,像汇编的DIV和IDIV,商回送AL或AX,余数回送AH或DX。
点赞  2008-4-22 20:15
引用: 引用 11 楼 fycom200 的回复:
引用 10 楼 lbing7 的回复:
10 / 2   
10 % 2  

编译器会给出一个优化的结果  
就是直接取其值  

当然,我一般不用单片机做大数或是浮点的运算.  
这仅仅是一个瞎想  

首先要感谢你的热情回复, 我实际看过KEIL C51生成的汇编码,这样的操作她是做了两次除法运算的,并且知道了余数就保存在R4,R5寄存器里(无符号 int 型除法),所以我打算直接把它取出来。  至于用单片机做除法运算这个是避免不了的,如果一要用到…
把编译器生成的代码单独取出来,写成可重定位的形式,单独编译成.lib文件,然后自己写一个.H文件,声明这个函数,不过把它的返回值声明成long型的,最后,返回值强制类型转换成int就得到商,返回值右移16位后强制类型转换成int就得到余数(不能声明成结构体,因为在Keil中,任何长度的结构体类型函数返回值都不通过寄存器传递)。
点赞  2008-4-23 17:43
补充说明:你如果在.H文件中把函数返回值声明成结构体类型,那么编译器会在调用该函数后到内存中的数据段中去找返回值,但你的.lib文件中的实现却是通过寄存器返回,而且不存在那个“数据段”,最终的结果可能是连接时错误或者在主调函数中得到垃圾数据。
点赞  2008-4-23 17:46
谢谢各位的热情帮助,揭贴~
点赞  2008-4-24 13:23
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复