|
楼主 |
发表于 2014-2-23 11:00:35
|
显示全部楼层
就为这我弄了半个小时, 查了ATMEL的规格书和INTEL 8051指令集. 写了一堆记录. 哈哈.
汇编:
org 0000h
mov p1, 55h
end
机器码:85 55 90
失败
C语言:
#inlucde <reg52.h>
void main()
{
P1=0x55;
}
机器码: 0000-080F
0000: 02 08 00 00 ..
反汇编:
02 08 00: LJMP 08 00 跳转到地址0800
Opcode: 0x02 instruction: LJMP code addr Bytes: 3 Flags: none
0800: 78 7F E4 F6 D8 FD 75 81 07 02 08 0C 75 90 55 22
反汇编:
78 7F: mov R0, 7Fh 0x78 mov R0, #data 2bytes
E4 : CLR A 0xE4 CLR A 1byte clear register A
F6 : mov @R0, A 0xF6 mov @R0, A 1byte
单片机mov R0, A和mov @R0, A的区别: mov R0, A 是把累加器中的数送给寄存器R0. mov @R0, A 是把累加器中的数, 送给R0内存储的地址单元. 这里是给7Fh地址赋值0
D8 FD: 0xD8 DJNZ R0, reladdr 2bytes decrement and jump if not zero
R0的值-1, 等于7Eh, 判断不为0, 向前跳转3BYTE, 也就是跳过了 D8 FD, 跳过了 F6, 开始从F6执行: 给地址7Eh赋值0. 如此循环.....直到R0的值为1, 给地址01h赋值0 执行D8 FD时, R0的值-1 等于0, 执行后面的语句 (地址00h的值没有被改变). 经过以上程序, 地址01-7F的值全部为0, 不明觉厉啊
75 81 07: mov iram addr, #data 把07h赋给internal RAM 81h; 查ATMEL的datasheet, 地址81h就是大名鼎鼎的SP (stack pointer). 难道上面那段代码是为了建立占空间? 为什么不把80h也改成0. 为什么不把00h也改成0
02 08 0C: ljmp code addr 这句可以不要,因为080C就在下面
75 90 55: mov iram addr, #data 把55h赋给90. 慢着, 8051instruction set关于MOV指令里有一行字:
** Note: In the case of "MOV iram addr,iram addr", the operand bytes of the instruction are stored in reverse order. That is, the instruction consisting of the bytes 0x85, 0x20, 0x50 means "Move the contents of Internal RAM location 0x20 to Internal RAM location 0x50" whereas the opposite would be generally presumed.
也就是说第一: 我上面那个汇编程序, 想把idata (55h)赋值给p1, 结果编译成了把地址55h里的值赋给90, 鬼知道地址55h里是什么数. 难怪出错. 因为没有查看8051的指令集, 想当然用了mov p1, 55h这样的赋值语句.
第二: 85这个opcode执行顺序是倒过来的, 就是把oprand 1 给oprand 2. 不过这个是机器的小癖好, 编译的时候两个操作数的顺序是倒着写的, 也就是负负为正了. 不需要特别留意.
22: ret
成功
汇编:
org 0000h
mov p1, #55h
end
机器码: 75 90 55
成功
心得: 没有汇编, 可以问别人, 发帖子, 程序也可以修改正确, 但我永远都不知道发生了什么. |
|