【技术问题】keil中的那些诡异事件。

[复制链接]
 楼主| 程序医人 发表于 2011-1-9 20:17 | 显示全部楼层 |阅读模式
来了21IC好些阵子了,一直靠发些半灌水贴以求混个脸熟。今天发个纯技术问题求教求教。 如题:hug: 。

1、keil中要对工作寄存器(R0,R1等)进行入栈出栈操作为什么不能直接用如PUSH R0、POP R0这样的写法,要用R0的地址,就是要这样:PUSH 00H、POP 00H?

2、C语言的问题。我写个式子:unsigned int a;    a=(168*196)/10;  结果a=62276,较真实结果大很多,而改成:unsigned int a;   a=168*196; a=a/10; 结果是a=3292;是正确的。  而如果 a=(167*196)/10;  结果也是真确的(167*196是32732,小于int型上限,(168*196)大于int型上限),我明明定义a是unsigned int 型上限是65535,不会越界的。 这是为什么? 不同的写法结果怎么不同?
cl378454434 发表于 2011-1-9 20:30 | 显示全部楼层
貌似LZ不给力啊,比较冷清啊,呵呵
xlsbz 发表于 2011-1-9 20:50 | 显示全部楼层
本帖最后由 xlsbz 于 2011-1-9 20:54 编辑

第二条  不可能!

如果可能的话,那就是C语言默认强制转换为int型的。


NND,一直以为我c语言基础不错 看样也不咋地!
rodger_br 发表于 2011-1-9 20:54 | 显示全部楼层
我来回答你吧。
1. PUSH、POP不支持寄存器寻址,只支持直接寻址。所以累加器进栈也似乎PUSH ACC,而不是PUSH A。
2. 编译器默认看来是有符号计算,所以你的结果实际上越界了。
原野之狼 发表于 2011-1-10 00:00 | 显示全部楼层
1、看汇编指令的寻址方式都有哪几种
2、问题不在于a是有符号还是无符号,而是后面的常数167或168被转化为int来处理。
ayb_ice 发表于 2011-1-10 08:30 | 显示全部楼层
这不是诡异事件,而是你不懂...

评分

参与人数 1威望 +1 收起 理由
moonsunsun + 1 你懂就说出来呀,让大家明白下 ...

查看全部评分

刘前辈 发表于 2011-1-10 09:33 | 显示全部楼层
本帖最后由 刘前辈 于 2011-1-10 10:02 编辑

谁说keil不支持 PUSH  R0 ;  ?只是你表达错了而已。
     以51为例,51有4个R0, 你 PUSH  R0;想PUSH 哪个R0? 所以你要写清楚:

        PUSH  AR0 ;  //AR0~AR7。 A大概是Address 的意思。
表示语句处由PSW——RSx确定的那个工作寄存器区(0~3)的当前的Rx;看下面:
    PSW_RS0=PSW_RS1=0;   
    PUSH  AR0 ;   
   PSW_RS0=PSW_RS1=1;
    PUSH  AR0 ;

2个推入的AR0是不一样的。


 楼主| 程序医人 发表于 2011-1-10 10:19 | 显示全部楼层
本帖最后由 程序医人 于 2011-1-10 10:51 编辑
1、看汇编指令的寻址方式都有哪几种
2、问题不在于a是有符号还是无符号,而是后面的常数167或168被转化为int来处理。
原野之狼 发表于 2011-1-10 00:00
   

1、51的工作寄存器其实不是在RAM中吗?这个MOV P1,R0  我觉得其实就是MOV P1,00H,不像8086寄存器是在CPU中的,寄存器没有地址,反正我是认为R0就像00H的一个标号。

2、我把unsigned int 换成unsigned long 和long问题依然,  这下不会越界了吧?
 楼主| 程序医人 发表于 2011-1-10 10:36 | 显示全部楼层
刘前辈,那招不行的,如果可以应该是编译器里事先定义了AR0这个符号了,我的KEIL里没有。
coody 发表于 2011-1-10 11:09 | 显示全部楼层
a =(uint)(168 * 196) / 10;这样就没问题了
twz8858877 发表于 2011-1-10 11:49 | 显示全部楼层
51的工作寄存器有4个区,根据PSW的不同,R0实际对应RAM的00H、08H、10H或18H,所以不能直接使用PUSH R0
 楼主| 程序医人 发表于 2011-1-10 11:54 | 显示全部楼层
感觉LS那种解释有道理,一条相同的指令不可能在不同的时候操作2个不同地址。
 楼主| 程序医人 发表于 2011-1-10 12:19 | 显示全部楼层
10楼的方法可以,可是为什么?
论坛游客 发表于 2011-1-10 12:38 | 显示全部楼层
5楼已经说过原因了
刘前辈 发表于 2011-1-10 13:56 | 显示全部楼层
本帖最后由 刘前辈 于 2011-1-10 14:03 编辑
#9楼
       刘前辈,那招不行的,如果可以应该是编译器里事先定义了AR0这个符号了,我的KEIL里没有


呵呵,前辈从不信口瞎说;中国人能想到的,德国人早就想到了。20年前的keil_A51就可以:——别太轻视德国人。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| 程序医人 发表于 2011-1-10 14:00 | 显示全部楼层
问题还没解决,就算是被当成int型了,那结果页不会是F344(负数),何况“=”也有自动数据类型转换的。   都说简单,请给个合理的解释呗!  不要说是语法问题,在VC中是没问题的。
 楼主| 程序医人 发表于 2011-1-10 14:15 | 显示全部楼层
本帖最后由 程序医人 于 2011-1-10 14:17 编辑

前辈请看,AR0(using1的时候)被换成08H了,说明AR0是keil中预先定义的符号。 不是C51指令中的关键字。
您在keil的安装目录中一定能找到此文件。
15# 刘前辈
mohanwei 发表于 2011-1-10 14:31 | 显示全部楼层
先把优化级别设置为0(也就是无优化)再测试这种玩意……
在资源本来就紧张的单片机里,如果
int i=0;
i=1;
i=2;
i=3;
i=4;
printf("%d",i);
也要把i折腾一遍再打印出来,那编译器就不用卖了:lol
 楼主| 程序医人 发表于 2011-1-10 14:50 | 显示全部楼层
我怀疑是在(168*196)/10时编译器直接把浮点数的编码赋值给了x,所以存入x中的是浮点数编码,导致出错。
刘前辈 发表于 2011-1-10 14:57 | 显示全部楼层
本帖最后由 刘前辈 于 2011-1-10 15:26 编辑
17#
   前辈请看,AR0(using1的时候)被换成08H了,说明AR0是keil中预先定义的符号。 不是C51指令中的关键字。
您在keil的安装目录中一定能找到此文件。


呵呵,LZ真逗,PUSH 0 是C51语句么?( 可别跟我说uV4 _PUSH_ )看清楚,我写的是aaa.A51.
无论 PUSH   0 还是  PUSH   AR0 都是keil 51汇编语句,和C51有什么关系?
AR0~AR7是keil_Ax51宏汇编器的保留关键字USING 是keil_Ax51汇编器的伪指令。——和C51无关。

你在keil 的安装目录下根本找不到这种预定义文件。
你应该说“AR0(在 using1 的时候)被编译成08H了”,哪有什么预定义转换文件,51 工作寄存器结构都一样,——预定义文件是那种必定要交给用户根据使用需要可修改的,LZ找到这个预定义文件了吗?如果有此文件,还算什么“诡异事件”。

20年前,还没有uV2 _IDE的时候,A51就接受 PUSH   ARx  这样的语句了;我们不知道而已。



/
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:程序医人=《程序医人》不是《程序匠人》!

1

主题

220

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部