转自:http://blog.csdn.net/yangzhiloveyou/article/details/6475607
RSEG是段选择指令,要想明白它的意思就要了解段的意思。
段是程序代码或数据对象的存储单位。程序代码放到代码段,数据对象放到数据段。
段分两种,一是绝对段,一是再定位段。绝对段在汇编语言中指定,在用L51联接的时候,地址不会改变。用于如访问一个固定存储器的i/o,或提供中断向量的入口地址。而再定位段的地址是浮动的。它的地址有L51对程序模块连接时决定,C51对源程序编译所产生的段都是再定位段,它都有段名和存储类型。绝对段没有段名。
说了这么多,大家可能还是不明白段是什么意思。别急,接着往下看。
例如,你写用C写了一个函数 void test_fun(void) { …} , 存在test.c中,用编译器编译以后. SRC FILE中看到:
?PR?test_fun?TEST SEGMENT CODE //(函数放到代码段中)
写这个函数体的时候:
RSEG ?PR?test_fun?TEST //选择已定位的代码段为当前段 test_fun:
……//代码
所以函数的表达模式是这样: ?PR?函数名?文件名
而函数名又分:
所以函数的表达模式是这样: ?PR?函数名?文件名
而函数名又分:
1:无参函数 ?PR?函数名?文件名
2:有参函数 ?PR?_函数名?文件名
3:再入函数 ?PR?_?函数名?文件名
又例如 你定义了全局变量 unsigned char data temp1,temp2; unsigned char xdata temp3; 在test.c文件中,编译器会为每个文件分0到多个全局数据段,相同类型的全局变量被存到同一段中。所以上面会编译成如下:
RSEG ? DT? TEST
. temp1: DS 1
. temp2: DS 1
;
RSEG ?XD? TEST
. temp3: DS 1
//下面是各个类型的数据全局段的表示
?CO? 文件名 //常数段
?XD? FILE_NAME //XDATA 数据段
?DT? FILE_NAME //DATA 数据段
?ID? FILE_NAME //IDATA…..
?BI? FILE_NAME // BIT …..
?BA? FILE_NAME //BDATA….
?PD? FILE_NAME //PDATA…..
看到这里大家应该明白段的意思了吧。也许你会问,这有什么作用哪?它就是用在当你需要用汇编语言写一部份程序的时候,把汇编写的函数放在这个问件中,改名xxx.a51,按上面的规则写。
编译就好。
既然知道了段的意思,现在我们回到SEG的用法上来。
A51中有两种段选择指令 : 再定位段选择指令 和 绝对段选择指令. 它们用来选择当前段是再定位段还是绝对段。使用不同的段选择指令,将使程序定位在不同的地址空间之内。
1: 再定位段的选择指令是: RSEG 段名
它用来选择一个在前面已经定义过的再定位段作为当前段。
用法就像我们上面的例子,先申明了一个函数段,后面写这个函数段。
2: 绝对段选择指令
CSEG [AT 绝对地址表达式] //绝对代码段
DSEG [AT 绝对地址表达式] //内部绝对数据段
XSEG [AT 绝对地址表达式] //外部绝对数据段
ISEG [AT 绝对地址表达式] //内部间接寻址绝对数据段
BSEG [AT 绝对地址表达式] //绝对位寻址段
它们的用法我举一个例子:
例如我们写串口中断程序,起始地址是0x23.就这样写
CSEG AT 0X23
LJMP serialISR
RSEG ?PR?serialISR?TEST
. serialISR:
设主调用模块函数为main call ( ) ,被调用的另一外
部模块函数为extern char afunc (char v a ,int v b) ,要求
函数afunc () 采用汇编语言编写。对于模块间的small 编
译下的C 语言调用汇编语言函数,可以采用如下的方法来
正确地编写汇编程序。
(1) 采用一般的写C51 程序方法,建立工程,在里面
导入main. c 文件和afunc. c 文件。
假设main. c 文件和afunc. c 具有如下格式:
/ / main call. c 模块文件
? / / 文件包含和其他定义
extern char afunc (char v a ,int v b) ; / / 对外部被调函数说明
void main call () { / / 主调函数
? / / 变量定义和其他语句
a = afunc (char v a ,int v b) ; / / 函数调用
}
/ / afunc. c 文件
? / / 文件包含和其他定义
char afunc (char v a ,int v b) { / / 被调用函数
char a ,retval ;int b ;
a = v a ;b = v b ;
return ( retval) ;
}
(2) 对afunc. c 文件设置SRC 编译控制命令
SRC 是一个十分有用的编译控制命令,他可令C51 编
译器将一个C 源文件编译成一个相应的汇编源文件。在
Keil c51 中,对Project 窗口中包含汇编代码的C 文件上
点击右键,选择“Options for file. . . ”选项,选中“Generate
Assembler SRC File”和“Assemble SRC File”选项,使之有
效,重新编译项目后就可生成afunc. src 文件,对src 文件
也可另存为asm 或a51 文件。在文件中加入pragma src
(afunc. a51) 控制命令,可直接生成afunc. a51 文件。
SRC 文件中包含了汇编程序中所需的所有接口信息,
afunc. src 主要内容如下:
2:有参函数 ?PR?_函数名?文件名
3:再入函数 ?PR?_?函数名?文件名
又例如 你定义了全局变量 unsigned char data temp1,temp2; unsigned char xdata temp3; 在test.c文件中,编译器会为每个文件分0到多个全局数据段,相同类型的全局变量被存到同一段中。所以上面会编译成如下:
RSEG ? DT? TEST
. temp1: DS 1
. temp2: DS 1
;
RSEG ?XD? TEST
. temp3: DS 1
//下面是各个类型的数据全局段的表示
?CO? 文件名 //常数段
?XD? FILE_NAME //XDATA 数据段
?DT? FILE_NAME //DATA 数据段
?ID? FILE_NAME //IDATA…..
?BI? FILE_NAME // BIT …..
?BA? FILE_NAME //BDATA….
?PD? FILE_NAME //PDATA…..
看到这里大家应该明白段的意思了吧。也许你会问,这有什么作用哪?它就是用在当你需要用汇编语言写一部份程序的时候,把汇编写的函数放在这个问件中,改名xxx.a51,按上面的规则写。
编译就好。
既然知道了段的意思,现在我们回到SEG的用法上来。
A51中有两种段选择指令 : 再定位段选择指令 和 绝对段选择指令. 它们用来选择当前段是再定位段还是绝对段。使用不同的段选择指令,将使程序定位在不同的地址空间之内。
1: 再定位段的选择指令是: RSEG 段名
它用来选择一个在前面已经定义过的再定位段作为当前段。
用法就像我们上面的例子,先申明了一个函数段,后面写这个函数段。
2: 绝对段选择指令
CSEG [AT 绝对地址表达式] //绝对代码段
DSEG [AT 绝对地址表达式] //内部绝对数据段
XSEG [AT 绝对地址表达式] //外部绝对数据段
ISEG [AT 绝对地址表达式] //内部间接寻址绝对数据段
BSEG [AT 绝对地址表达式] //绝对位寻址段
它们的用法我举一个例子:
例如我们写串口中断程序,起始地址是0x23.就这样写
CSEG AT 0X23
LJMP serialISR
RSEG ?PR?serialISR?TEST
. serialISR:
设主调用模块函数为main call ( ) ,被调用的另一外
部模块函数为extern char afunc (char v a ,int v b) ,要求
函数afunc () 采用汇编语言编写。对于模块间的small 编
译下的C 语言调用汇编语言函数,可以采用如下的方法来
正确地编写汇编程序。
(1) 采用一般的写C51 程序方法,建立工程,在里面
导入main. c 文件和afunc. c 文件。
假设main. c 文件和afunc. c 具有如下格式:
/ / main call. c 模块文件
? / / 文件包含和其他定义
extern char afunc (char v a ,int v b) ; / / 对外部被调函数说明
void main call () { / / 主调函数
? / / 变量定义和其他语句
a = afunc (char v a ,int v b) ; / / 函数调用
}
/ / afunc. c 文件
? / / 文件包含和其他定义
char afunc (char v a ,int v b) { / / 被调用函数
char a ,retval ;int b ;
a = v a ;b = v b ;
return ( retval) ;
}
(2) 对afunc. c 文件设置SRC 编译控制命令
SRC 是一个十分有用的编译控制命令,他可令C51 编
译器将一个C 源文件编译成一个相应的汇编源文件。在
Keil c51 中,对Project 窗口中包含汇编代码的C 文件上
点击右键,选择“Options for file. . . ”选项,选中“Generate
Assembler SRC File”和“Assemble SRC File”选项,使之有
效,重新编译项目后就可生成afunc. src 文件,对src 文件
也可另存为asm 或a51 文件。在文件中加入pragma src
(afunc. a51) 控制命令,可直接生成afunc. a51 文件。
SRC 文件中包含了汇编程序中所需的所有接口信息,
afunc. src 主要内容如下:
NAME AFUNC / / 函数名
? PR ? afunc ? AFUNC SEGMENT CODE
/ / 定义程序代码段
? DT ? afunc ? AFUNC SEGMENT DATA OVERLA YABL E
/ / 定义可覆盖局部数据段
PUBL IC afunc / / 共公符号定义
RSEG ? DT ? afunc ? AFUNC / / 可覆盖局部数据段
? afunc ? BYTE: / / 起始地址
a ? 042 : DS 1 / / 定义其他局部变量
b ? 043 : DS 2
retval ? 044 : DS 1
RSEG ? PR ? afunc ? AFUNC / / 程序代码段
afunc : / / 汇编程序起始地址
USING 0 / / 工作寄存器0 组
MOV a ? 042 ,R7 / / 第一参数传递
MOV b ? 043 ,R4 / / 第二参数传递高位 c51编译器中int型数据高八位存于低地址,低八位存于高地址
MOV b ? 043 + 01H ,R5 / / 第二参数传递低位
MOV R7 ,retval ? 044 + 01H / / 函数返回值
? C0001 :
RET
END
(3) 将afunc. src 文件另存为afunc. asm(或afunc.
a51) 文件,在工程中移去afunc. c 文件,添加afunc. asm(或
afunc. a51) 文件,再次编译工程可得到汇编函数的主体,根
据需要修改函数里面的汇编代码就得到所需的汇编函数
了。应注意局部变量的使用:局部变量按照C51 的格式定
义后,才能进行优化分析。
(4) 对C51 中调用的汇编程序,如果不想使用以上的
方式建立接口,则可以依据Cx51 规则,按照自己的想法来
建立接口,使得汇编程序显得简洁、易读。下列程序是上
例程序中建立汇编程序接口实例,使用寄存器进行参数传
递,并定义一局部变量MMP。
PUBL IC AFUNC / / 定义共公符号“, ”表示有参数传递
LLL SEGMENT CODE
/ / 定义程序代码段,LLL 为标识符,可任意
PUBL IC / / 定义共公符号, 为局部变量的共公符号
LL T SEGMENT DATA OVERLA YABL E
/ / 定义可覆盖局部数据段
RSEG LL T / / 可覆盖局部数据段
PPP : / / 定义局部变量
MMP : DS 2 / / 定义局部变量字节,MMP 为局部变量,两字节
RSEG LLL / / 程序代码段
afunc : / / 程序代码段起始地址
MOV 00H ,R7 / / 汇编程序行
MOV MMP + 1 ,R4 / / 局部变量使用
MOV MMP ,R5
MOV R7 ,02H
RET
END
? PR ? afunc ? AFUNC SEGMENT CODE
/ / 定义程序代码段
? DT ? afunc ? AFUNC SEGMENT DATA OVERLA YABL E
/ / 定义可覆盖局部数据段
PUBL IC afunc / / 共公符号定义
RSEG ? DT ? afunc ? AFUNC / / 可覆盖局部数据段
? afunc ? BYTE: / / 起始地址
a ? 042 : DS 1 / / 定义其他局部变量
b ? 043 : DS 2
retval ? 044 : DS 1
RSEG ? PR ? afunc ? AFUNC / / 程序代码段
afunc : / / 汇编程序起始地址
USING 0 / / 工作寄存器0 组
MOV a ? 042 ,R7 / / 第一参数传递
MOV b ? 043 ,R4 / / 第二参数传递高位 c51编译器中int型数据高八位存于低地址,低八位存于高地址
MOV b ? 043 + 01H ,R5 / / 第二参数传递低位
MOV R7 ,retval ? 044 + 01H / / 函数返回值
? C0001 :
RET
END
(3) 将afunc. src 文件另存为afunc. asm(或afunc.
a51) 文件,在工程中移去afunc. c 文件,添加afunc. asm(或
afunc. a51) 文件,再次编译工程可得到汇编函数的主体,根
据需要修改函数里面的汇编代码就得到所需的汇编函数
了。应注意局部变量的使用:局部变量按照C51 的格式定
义后,才能进行优化分析。
(4) 对C51 中调用的汇编程序,如果不想使用以上的
方式建立接口,则可以依据Cx51 规则,按照自己的想法来
建立接口,使得汇编程序显得简洁、易读。下列程序是上
例程序中建立汇编程序接口实例,使用寄存器进行参数传
递,并定义一局部变量MMP。
PUBL IC AFUNC / / 定义共公符号“, ”表示有参数传递
LLL SEGMENT CODE
/ / 定义程序代码段,LLL 为标识符,可任意
PUBL IC / / 定义共公符号, 为局部变量的共公符号
LL T SEGMENT DATA OVERLA YABL E
/ / 定义可覆盖局部数据段
RSEG LL T / / 可覆盖局部数据段
PPP : / / 定义局部变量
MMP : DS 2 / / 定义局部变量字节,MMP 为局部变量,两字节
RSEG LLL / / 程序代码段
afunc : / / 程序代码段起始地址
MOV 00H ,R7 / / 汇编程序行
MOV MMP + 1 ,R4 / / 局部变量使用
MOV MMP ,R5
MOV R7 ,02H
RET
END
转载于:https://blog.51cto.com/dong4716138/1117812