打印

51指令?

[复制链接]
3987|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
jakey0225|  楼主 | 2007-10-26 09:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
5880527| | 2007-10-26 09:53 | 只看该作者

PUSH 01H

使用特权

评论回复
板凳
fsaok| | 2007-10-26 09:56 | 只看该作者

.

mov a, r1
push acc

使用特权

评论回复
地板
ayb_ice| | 2007-10-26 11:03 | 只看该作者

多看书

使用特权

评论回复
5
hab2000| | 2007-10-26 14:15 | 只看该作者

2楼正解!

使用特权

评论回复
6
xwj| | 2007-10-26 14:25 | 只看该作者

因为51有4组寄存器,R1可能对应到4个地址,编译器没法确定该用

而PUSH xx是绝对寻址,地址固化在程序代码中了,编译器没法没法判断你到底用的那个寄存器组以及你是否切换过寄存器组,无法确定该用哪个地址,所以只能报错!


因此应该如2楼所说那样: PUSH  01H(当前用得是默认的寄存器组0)

使用特权

评论回复
7
ayb_ice| | 2007-10-26 15:04 | 只看该作者

3楼才是正解

当然能确定当前的寄存器组的话,直接入栈直接地址是可以的,C51里这两种方法是可选的

使用特权

评论回复
8
computer00| | 2007-10-26 15:21 | 只看该作者

push pop只能对地址操作,不能对寄存器操作

使用特权

评论回复
9
jerkoh| | 2007-10-26 16:58 | 只看该作者

同意00的说法

R0是寄存器,要对它做保护, 只能用它地址 00H

使用特权

评论回复
10
沈老| | 2007-10-26 20:13 | 只看该作者

如果是KEIL的A51

USING   0;(0-3) 必须加这句,告诉编译器
;程序现在使用BANK0(0-3)
;现在可以用R0的重复表示AR0等
PUSH    AR1;=R0->R7
POP     AR1;=R0->R7
一般复位后PSW=0,也就是使用BANK0.

使用特权

评论回复
11
mohanwei| | 2007-10-26 22:00 | 只看该作者

三楼的做法才是正道……

使用特权

评论回复
12
沈老| | 2007-10-27 09:22 | 只看该作者

看看编译器如何做

下面是一段C程序:
#include <stdio.h>
int interruptcnt;
int second;
void timer0 (void) interrupt 1 // 注意没有使用 "using 2"
{
    if (++interruptcnt == 4000) 
    { /* count to 4000 */
        second++; /* second counter */
        interruptcnt = 0; /* clear int counter */
    }
}

void main(void)
{
    interruptcnt=0;
    second=0;
    printf("I do it in this way !");
}
编译器产生的T0中断的LST文件如下:
             ; FUNCTION timer0 (BEGIN)
0000 C0E0              PUSH    ACC
0002 C0D0              PUSH    PSW;!!!!!!!!!!!!!!!!!!!!!!!!
0004 75D000            MOV     PSW,#00H;!!!!!!!!!!!!!!!!!!!
0007 C006              PUSH    AR6;!!!!!!!!!!!!!!!!!!!!!!!!
0009 C007              PUSH    AR7;!!!!!!!!!!!!!!!!!!!!!!!!
                                           ; SOURCE LINE # 9
                                           ; SOURCE LINE # 11
000B 0500        R     INC     interruptcnt+01H
000D E500        R     MOV     A,interruptcnt+01H
000F 7002              JNZ     ?C0004
0011 0500        R     INC     interruptcnt
0013         ?C0004:
0013 FF                MOV     R7,A
0014 AE00        R     MOV     R6,interruptcnt
0016 BE0F11            CJNE    R6,#0FH,?C0002
0019 BFA00E            CJNE    R7,#0A0H,?C0002
                                           ; SOURCE LINE # 12
                                           ; SOURCE LINE # 13
001C 0500        R     INC     second+01H
001E E500        R     MOV     A,second+01H
0020 7002              JNZ     ?C0005
0022 0500        R     INC     second
0024         ?C0005:
                                           ; SOURCE LINE # 14
0024 750000      R     MOV     interruptcnt,#00H
0027 750000      R     MOV     interruptcnt+01H,#00H
                                           ; SOURCE LINE # 15
                                           ; SOURCE LINE # 16
002A         ?C0002:
002A D007              POP     AR7;!!!!!!!!!!!!!!!!!!!!!!!!!!!!
002C D006              POP     AR6;!!!!!!!!!!!!!!!!!!!!!!!!!!!!
002E D0D0              POP     PSW;!!!!!!!!!!!!!!!!!!!!!!!!!!!!
0030 D0E0              POP     ACC
0032 32                RETI    
             ; FUNCTION timer0 (END)

使用特权

评论回复
13
wxj1952| | 2007-10-27 12:33 | 只看该作者

考虑后果

假定3楼正解。如果要把R1~R7入栈,将成为:
MOV A,R1
PUSH ACC
MOV A,R2
PUSH ACC
MOV A,R3
PUSH ACC
......

出栈时:
POP ACC
MOV R7,A
POP ACC
MOV R6,A
......
谁也看不懂,连自己都要小心弄错。


再看2楼:假设要把01区的R1~R7入栈:
PUSH  9
PUSH  0AH
PUSH  0BH
......
出栈时:
POP  ?
.......
POP 0BH
POP 0AH
POP 9


再看按照规范: 
using 1  ;或者using 0/using 2/using 3  
PUSH  AR1
PUSH  AR2
PUSH  AR3
......

出栈时
POP  AR7
POP  AR6
POP  AR5
...... 
POP  AR2
POP  AR1

使用特权

评论回复
14
ayb_ice| | 2007-10-27 15:20 | 只看该作者

随便说说

如果KEIL不选中“使用绝对寄存器访问”选项的话,就是产生
MOV ACC,R0
PUSH ACC
这样的指令,这样的方式适应性更强,可以使用任意寄存器组,而PUSH AR0的方式是做不到的,当然这样效率高些,但当寄存器组被改变时是不行的。。。

使用特权

评论回复
15
wxj1952| | 2007-10-27 18:50 | 只看该作者

一头雾水。

“而PUSH AR0的方式是做不到的,......当寄存器组被改变时是不行的。。。”

搞不懂了,您在任意寄存器组下可以用R0, AR0却不可以在任意寄存器组下用?那ARx什么情况下用?

任意寄存器组下,都是PUSH AR0/POP AR0 。

使用特权

评论回复
16
赤铸| | 2007-10-28 00:29 | 只看该作者

AR0 ≠ R0

这正是因为 51 的寄存器的双重属性:既是寄存器,又占用普通 RAM 变量的空间。
用AR0,AR1就是把寄存器当作普通变量存取。但R0,R1……对应的实际RAM地址随当前寄存器页而变,只有在寄存器页0下,AR0和R0才是同一个东西

PUSH AR1 跟前面的 PUSH 01H 其实是一回事

使用特权

评论回复
17
hotpower| | 2007-10-28 00:39 | 只看该作者

关键和PSW有关~~~

使用特权

评论回复
18
wxj1952| | 2007-10-28 11:26 | 只看该作者

专家真多

Keil/Franklin 在1988年就已经修改了这一点不足,我们过了20年还在讨论。

Keil的宏汇编中的using n 语句其实就是为了简化编程员对PSW的设置,而随using n 语句而改变的就是ARx。(ARx我想大概是Address of Rx之意吧。)由于有了using n /ARx ,那种RS1/RS0/Rx 在小汇编里的用法,是不是太传统的用法?也就是说我们20年来没学新技术,或者是太看不上汇编语言。

举例:
using 1
......
PUSH  AR0
......
using  2
PUSH  AR0
using  3
PUSH  AR0

汇编后代码为:(已经没有了对PSW/RS1/RS0的处理语句!)
C008  PUSH  08H    
......
C010  PUSH  10H
C018  PUSH  18H
END

对照小汇编:
CLR SR1
SETB SR0 
MOV A,R0
PUSH  ACC
SETB SR1
CLR SR0
MOV A,R0
PUSH  ACC
SETB SR0 
MOV A,R0
PUSH ACC
END

但是如果
CLR SR1
SETB SR0 
MOV A,AR0 ;-----
PUSH  ACC

怀疑是不是想在传统与现代之间搭一座桥梁?


使用特权

评论回复
19
wxj1952| | 2007-10-28 11:34 | 只看该作者

对自己说的每句话负责

“只有在寄存器页0下,AR0和R0才是同一个东西”

“PUSH AR1 跟前面的 PUSH 01H 其实是一回事”

显然,第一句话正确,第二句话错了。概念没理解。

有没有人会说:“对不起,我说错了。”


使用特权

评论回复
20
ayb_ice| | 2007-10-29 08:19 | 只看该作者

回20楼

“只有在寄存器页0下,AR0和R0才是同一个东西”这句话错了。。。
后面那句也不正确。。。
AR0等于R0的直接寻址方式,可能是00H,08H,10H,18H,这取决于using n...

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

25

主题

45

帖子

0

粉丝