1. 汇编代码的变量一般是自己定义地址空间, 而C是由编译器进行分配,分配空间在下面截图黑框分别设置code memory和xdata memory.注意避开汇编使用到的地址,可以忽略汇编代码部分和DB字段定义的部分,但是要注意EQU字段定义的宏,它可能是定义为地址空间使用,还有要注意之前汇编使用的地址段,用来存储变量,但是没有用DB字段进行初始化。
2.小心局部变量,如果上图memory model选择的是in data,那将默认存储在内部存储器data区空间,下表示定义变量时加下述关键字,能定义变量到相应区域
存储类型 | 说明 |
data | 直接访问内部数据存储器(128字节),访问速度最快 |
bdata | 可位寻址内部数据存储器(16字节0x20-0x2f),允许位与字节混合访问 |
idata | 间接访问内部数据存储器(256字节),允许访问全部内部地址 |
pdata | 分页访问外部数据存储器(256字节),用MOVX @Ri指令访问 |
xdata | 外部数据存储器,用MOVC @DPTR指令访问 |
code | 程序存储器,用MOVC @A+DPTR指令访问 |
3. 汇编调用C代码,当代码有传递参数时,在C函数名前加下划横杠,没有则为C函数名,传递给C的变量通过中间寄存器实现, 如下表:
参数 | char | int | long/float | 通用指针 |
第一个 | R7 | R6,R7 | R4~R7 | R1,R2,R3 |
第二个 | R5 | R4,R5 | R4~R7 | R1,R2,R3 |
第三个 | R3 | R2,R3 | NULL | R1,R2,R3 |
返回值类型 | 寄存器 | 说明 |
Bit | C | 由位运算器C返回 |
(unsigned)char | R7 | 在R7返回单个字节 |
(unsigned)int | R6,R7 | 高位在R6低位在R7 |
(unsigned)long | R4~R7 | 高位在R4低位在R7 |
float | R4~R7 | 32位EEE格式 |
通用指针 | R1,R2,R3 | 存储类型在R3高位在R2地位在R1 |
例子如下,
a.下面MACRO宏定义可以当作C函数调用的方式使用,很方便;
b. 注意 _UartPutx 需要在使用的.asm文件定义
extrn code(_UartPutc):
PCHAR MACRO Tmp
MOV R7, Tmp
CALL _UartPutx ;UartPutx为C代码,只有一个参数
ENDM
4. 汇编中如果用了地址自增(DPTR自增),这在汇编代码是很常见的,因为这个能简化汇编操作.但是这里在C中存在很大问题,如果C中存在地址指针的操作,必定会存在问题,当C代码由编译器转化为汇编时,就会有对DPTR的使用.如果汇编里使能了地址自增,再调用了C代码,而C代码没有失能,那将会导致地址错乱.下面列举了几个C编译为汇编用到DPTR的情况,还会有其他情况,不一一列举:
a.定义了一个外部变量,外部变量有使用到
u16 xdata cmp_err_bits;
cmp_err_bits = 200;
编译为汇编代码:
MOV DPTR,#cmp_err_bits?747
MOVX @DPTR,A ;运算完自动递增一次
INC DPTR ;这里又自增一次,本来只需要自增一次,但这里实际自增两次了
MOV A,#0C8H
MOVX @DPTR,A
b.对地址指针的操作,这里不列举出汇编代码
*((u8 xdata*)(CACHE+IndexSec)) = cmp_err_bits;