搜索

C51嵌入汇编, 这几天一直折腾,稍微有点头绪了

[复制链接]
2658|4
 楼主 | 2009-3-10 23:44 | 显示全部楼层 |阅读模式
1. 直接内嵌汇编程序:
void x(void)
{
#pragma asm
汇编程序
#pragma endasm
}
2. C调用汇编
(1)x.asm
$NOMOD51
#include <C8051F120.h>
;这样的话就可以直接用C的库函数
PUBLIC    bSram_Num; 声明变量和函数名
PUBLIC    _Ram_Write_Byte; 函数名一定要加下划线,被这个下划线搞死了

SRAM_PROG_REG SEGMENT DATA     ; 
    RSEG SRAM_PROG_REG ; 表示下面声明的变量在DATA区0~7F
bSram_Num: DS 1 ; 声明变量为1 byte型

SRAM_PROG_REG SEGMENT XDATA     ; 
    RSEG SRAM_PROG_REG ; 表示下面声明的变量在XDATA区
V1: DS 1 ; 声明变量为1 byte型,有点不准确(可能叫V1的存储空间在XDATA 区,大小为1 BYTE)
V2: DS 100 ; 声明变量为2 bytes型(同上)
;.....

;---------------;
; ABC EQU BCD
; EDF DATA 0x90
;;等等A51的宏汇编指令
;----------------;

SRAM_PROG_CODE    SEGMENT    CODE
    RSEG  SRAM_PROG_CODE ;下面是代码

    USING    0; 告诉编译器现在使用的是第0组寄存器

_Ram_Write_Byte:
    P4 = R6;
    P7 = R7;    第一个word型参数

    P5 = R5;
    P6 = R4;   第二个word型参数
    
    DPL = R3;  word xdata型参数
    DPH = R2;   
    
    MOV A, bSram_Num ;最后一个byte型参数
    RET
END
;;---------------------------------------------------
;如果加入中断的话如下:

PUBLIC    DRIVER_ISR;这里好像不用加下划线(实际测试是这样的)

    CSEG    AT    0000BH
    LJMP    DRIVER_ISR

DRIVER_ISR_PROG   SEGMENT CODE
    RSEG  DRIVER_ISR_PROG
Driver_ISR:
    PUSH    ACC
    PUSH    DPH
    PUSH    DPL
    PUSH    PSW
    USING    3

    POP....
        RETI
END
;以上为ASM文件。
;;---------------------------------------------------

(2)
//以下为C文件
void Ram_Write_Byte(word xPOS, word yPos, word xdata *prData, byte bSram_Num );//这时的函数声明不再用下划线了。

void sram_test(void)
{
    byte i;
    word x, y;
    word xdata pdata[20] = {0,...,0};
    i = 20;
    Ram_Write_Byte(x,y,pdata, i);
}
3. 另一种做法:
(1)先写一个C的文件,然后,选择SRC编译。
(2)打开生成的SRC文件,按需要修改成自已想要的汇编程序。
(3)删除原来的C文件,加入修改后的SRC再编译。
第三种方法最好实现,但是本人不是很喜欢,代码看上去太乱了,而且

希望以上这些能够对像我一样想嵌入汇编的盲人有点帮助。
注:1. 以上很有可能有不对或不妥之处,请帮忙更正。
    2. 因本人在这方面能力有限,不要有JJYY的。
| 2009-3-11 00:20 | 显示全部楼层

不错~~~俺现在玩的是汇编数组~~~

/*-----------------------------------------------------------------------
        函数Week(macro_U16_arg1, macro_U8_arg2, macro_U8_arg3)
入口:
        macro_U16_arg1 年(0x00~0x9999)BCD码
        macro_U8_arg2  月(0x01~0x12)BCD码
        macro_U8_arg3  日(0x01~0x31)BCD码
出口:
        macro_U8_Result 星期(0~6)
长度:   82字节
-----------------------------------------------------------------------*/
macro_Function_Arg3 (Week, macro_U16_arg1, macro_U8_arg2, macro_U8_arg3)
{
#define Week_LOOP -20
    asm_MOV_R1(4),//将百年、年、月、日的BCD码换成二进制数
//Week_LOOP:
    asm_MOV_A(0x4f),//DataBuffer偏移,程序长度
//分别取出macro_U16H_arg1,macro_U16L_arg1macro_U8_arg2, macro_U8_arg3
    asm_MOVC_A_aDPTR(),
    asm_MOV_R0_A(),
    asm_MOV_A_iR0(),
    asm_ANL_A(0x0f),
    asm_XCH_A_iR0(),
    asm_SWAP_A(),
    asm_ANL_A(0x0f),
    asm_MOV_B(10),
    asm_MUL_AB(),
    asm_ADD_A_iR0(),
    asm_MOV_iR0_A(),
    asm_INC_DPTR(),
    asm_DJNZ_R1(Week_LOOP),//四次未完继续
//(星期=百年%4*5+年+年/4+(13*月+8)/5+日)%7,特别注意1月2月的年为"去年"
    asm_CJNE_Rn(macro_U8_arg2, 0x03, 0),//判断月
    asm_JNC(size_MOV_A_Rn() + size_ORL_A() + size_MOV_Rn_A() 
            + size_DEC_Rn() + size_CJNE_Rn() + size_DEC_Rn()),//月
//月<=2
    asm_MOV_A_Rn(macro_U8_arg2),
    asm_ORL_A(0x04),//1月2月同5月六月表
    asm_MOV_Rn_A(macro_U8_arg2),
    asm_DEC_Rn(macro_U16L_arg1),//1月2月的年为"去年"
    asm_CJNE_Rn(macro_U16L_arg1, 0xff, size_DEC_Rn()),//Week_Start
    asm_DEC_Rn(macro_U16H_arg1),
//Week_Start:
//百年%4*5
    asm_MOV_A_Rn(macro_U16H_arg1),//百年
    asm_ANL_A(0x03),
    asm_MOV_Rn_A(macro_U16H_arg1),//百年%4
    asm_CLR_C(),
    asm_RLC_A(),
    asm_CLR_C(),
    asm_RLC_A(),//百年%4*4
    asm_ORL_A_Rn(macro_U16H_arg1),//百年%4*5
    asm_MOV_Rn_A(macro_U16H_arg1),//保存(百年%4*5),最大值3*5=15
//年+年/4
    asm_MOV_A_Rn(macro_U16L_arg1),//年
    asm_CLR_C(),
    asm_RRC_A(),
    asm_CLR_C(),
    asm_RRC_A(),
    asm_ADD_A_Rn(macro_U16L_arg1),//年+年/4
    asm_MOV_Rn_A(macro_U16L_arg1),//保存(年+年/4),最大值99+25=124
    asm_MOV_A_Rn(macro_U8_arg2),//月
    asm_MOV_B(13),
    asm_MUL_AB(),//13*月->A
    asm_MOV_B(8),
    asm_ADD_A_B(),//13*月+8
    asm_MOV_B(5),
    asm_DIV_AB(),//(13*月+8)/5 商->A
    asm_MOV_Rn_A(macro_U8_arg2),//保存((13*月+8)/5)最大值33
//日
    asm_ADD_A_Rn(macro_U8_arg3),//日,最大值31
    asm_ADDC_A_Rn(macro_U16H_arg1),//(百年%4*5),最大值15
    asm_ADDC_A_Rn(macro_U16L_arg1),//(年+年/4),最大值99+25=124
/*
此时ACC最大为15+124+33+31=203,
注意,蔡勒公式内无203.-2*C可能会越界,菜农给出的蔡勒公式完整表述:
W = (203+C/4-2*C+Y+Y/4+(13*M+8)/5+D)%7
菜农星期公式:
W = (    C%4*5+Y+Y/4+(13*M+8)/5+D)%7
*/
    asm_MOV_B(7),//取余数%7
    asm_DIV_AB(),
    asm_XCH_A_B(),
    asm_MOV_Rn_A(macro_U8_Result),//送返回值(星期)
    macro_return(),
//数据区DataBuffer
    asm_DB(macro_U16H_arg1),
    asm_DB(macro_U16L_arg1),
    asm_DB(macro_U8_arg2),
    asm_DB(macro_U8_arg3)
};

使用特权

评论回复
| 2009-3-11 20:48 | 显示全部楼层

研究这些玩意儿

不如研究研究程序框架

使用特权

评论回复
| 2009-3-11 21:07 | 显示全部楼层

顶一个

使用特权

评论回复
 楼主 | 2009-3-11 21:13 | 显示全部楼层

嵌入汇编实属无奈之举,用C速度达不到

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /4 下一条

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