在fc中怎么给变量分配地址

在fc中怎么给变量分配地址,第1张

如何分配变量到指定的地址

举例:

unsigned char temp_A@0x00//定义无符号变量temp_A,强制其地址为0x00

unsigned char temp_B@0x100//定义无符号变量temp_B,强制其地址为0x100

@tiny unsigned char temp_C//定义无符号变量temp_C,由编译器自动在地址小于0x100的RAM中为其分配一个地址

@near unsigned char temp_D//定义无符号变量temp_D,由编译器自动在地址大于0xFF的RAM中为其分配一个地址

另外也可以采用伪指令"pragma"将函数或者变量定义到指定的section中,例如:

#pragma section [name] // 将下面定义的未初始化变量定义到.name section中

Unsigned char data1

Unsigned int data2

……(任何需要定义在.name section中的变量)

……

#pragma section [] // 返回到正常的section.

注意:pragma伪指令可以用来定位函数,初始化变量或者未初始化变量。这三者用不同的括号区分。

(name):代码

[name] :未初始化变量

{name}:初始化变量

如何在COSMIC C文件中使用汇编语言

在COSMIC C文件中使用汇编语言常见的方法有如下两种:使用#asm …#endasm组合格式

或_asm("…")单行格式。

举例1:

unsigned char temp_A

Void func1(void)

{

...

#asm

PUSH A

LD A,(X)

LD _temp_A,A

POP A

#endasm

...

}

注:在C嵌汇编环境下使用全局变量,要在该全局变量名称前加下划线"_"。

举例2:

Void func1(void)

{

...

_asm("rim")

_asm("nop")

...

}

如何观察RAM/FLASH/EEPROM的最终分配情况

在Project->settings->linker选项页中,将Category选为Output,再勾选Generate Map File。

点击OK按键后,再次编译链接该项目,如果成功则会在项目输出目录中(本例是在C:\STM8_NewProject1\debug 目录下)生成 .map 文件。该文件详细地列出RAM/FLASH/EEPROM的分配使用情况。

如何生成hex格式的输出文件

在Project->settings->PostBuild选项页中,在commands栏内加入下行命令:

chex –fi -o $(OutputPath)$(TargetSName).hex $(OutputPath)$(TargetSName).sm8

再次编译链接该项目,如果成功则会在项目输出目录中(本例是在C:\STM8_NewProject1\debug 目录下)生成 .hex 文件。

什么是MEMORY MODEL

STM8的C编译器支持多种存储器模式。http://tiyubisai.com/video_news/news_135621.html 用户可以根据应用的需要选择最适合的配置。可以根据需要选择采用2个字节的寻址方式(仅适用于64k以内的程序)或老迟者3字节的寻址方式。也可以规定将变量默认为定义在存储器的哪一区域:zero page内,汪察还是zero page 外。下面对几种供选择的MEMORY MODEL做简单说明。

在Project->settings->C Complier选项页中,将Category选为General,里面有一个Memory Models选项栏如下:

在下拉菜单中共有4种MEMORY MODEL可供选择:

程困含茄序地址空间在64K以内(即程序容量小于32K)

mods0,

modsl0

程序地址哦那个键在64K以上(即程序容量大于32K)

mods

modsl

MODS0 MODSL0 MODS MODSL

名称 Stack Short

短堆栈模式 Stack Long

长堆栈模式 Stack Short

短堆栈模式 Stack Long

长堆栈模式

程序地址空间 程序所用到的地址空间在64K范围内 程序所用到的地址空间超出64K范围

指针默认类型 函数指针和数据指针默认为@near (2 bytes) 函数指针默认为@far(地址为3字节);

数据指针默认为@near

全局变量默认类型 所有全局变量的地址默认为1个字节。对于地址超出1个字节的变量,必须用@near定义 所有全局变量默认为Long型。若要将变量地址定义为1个字节,必须用@tiny定义 所有全局变量的地址默认为1个字节。对于地址超出1个字节的变量,必须用@near定义 所有全局变量默认为Long型。若要将变量地址定义为1个字节,必须用@tiny定义

.lkf 文件的作用

.lkf文件在程序链接时决定如何具体分配RAM/ROM的空间。在Project Settings – Linker – Category(Input)选项页中,当"Auto"选择框被选中时,由系统自动生成.LKF文件,否则由用户指定。

当"Auto"选择框被勾选时,.lkf文件会自动生成在项目主目录下的 debug/ 和 release/ 目录中。下面以上图所示 at45DBXX Project的 lkf 文件为例,来进一步理解.lkf 。

在.lkf中,以"#"开头的行是注释行,为方便用户理解,将原注释删除,代之以中文注释如下:

# 定义(+seg)一个常量段(.const),开始(b)于0x8080,最大分配(m)0x1ff80个字节(即不超过

# 0x27FFF),为该段起名(n)为.const(和常量段的保留字同名),需要初始化的变量的初始值存

# 放于此段(-it)

+seg .const -b 0x8080 -m 0x1ff80 -n .const -it

# 定义(+seg)一个程序段(.text),紧跟(-a)在.const段后面(和.const 共同位于0x8080 –

# 0x27FFF),为该段起名(n)为. text (和程序段的保留字同名)。

+seg .text -a .const -n .text

# 定义(+seg)一个EEPROM段(.eeprom),开始(b)于0x4000,最大分配(m)0x800个字节(即不超

#过0x47FF),为该段起名(n)为. eeprom (和EEPROM段的保留字同名)。

+seg .eeprom -b 0x4000 -m 0x800 -n .eeprom

# .bsct段服务于定义在0页(地址小于0x100)以内需要初始化的全局变量(如@tiny char a = 9)

+seg .bsct -b 0x0 -m 0x100 -n .bsct

# .ubsct段服务于定义在0页(地址小于0x100)以内不需要初始化的全局变量(如@tiny char b)

+seg .ubsct -a .bsct -n .ubsct

# .bit表示位域段,定义后即可在程序中使用_Bool变量(如_Bool c = 1),-id表示该段需要初始化。

+seg .bit -a .ubsct -n .bit -id

# 这是ST7时代(STM8是基于ST7发展而来的)由于物理堆栈小,速度慢,使用内存来模拟堆栈的变通手段。

+seg .share -a .bit -n .share -is

# .data段服务于定义在0页(地址大于0xFF)以外需要初始化的全局变量(如@near char d = 8)

+seg .data -b 0x100 -m 0x1300 -n .data

# .bss段服务于定义在0页(地址大于0xFF)以内不需要初始化的全局变量(如@ near char e)

+seg .bss -a .data -n .bss

# 段定义结束,下面放置的库及Obj文件中的变量、常量、程序就按照上面的规定进行分配。

#初始化程序

crtsi0.sm8

#用户程序

Debug\main.o

# 一些必要的cosmic库

libis0.sm8

libm0.sm8

# 重定义常量段,开始于0x8000,用于放置中断向量表(STM8硬件决定此位置)

# –k 用于程序冗余代码优化,详情可参考cosmic用户手册。

+seg .const -b 0x8000 –k

# 中断向量

Debug\stm8_interrupt_vector.o

#定义了三个变量,用于系统初始化

+def [email protected] # end of uninitialized zpage

+def [email protected] # end of bss segment

+def __stack=0x17ff # 不同的芯片__stack内容不同,由系统自动生成

如何实现位 *** 作

Cosmic C 编译器支持位变量的 *** 作,可以将其定义成 _Bool类型。_Bool类型的变量只包含两种值true(1)或者false(0)。若将一个表达式赋值给_Bool变量,则编译器会将表达式与0做比较,然后将布尔值赋给_Bool变量。因此,任何整型或者表达式的值都可以赋给_Bool变量。但是,布尔变量不能定义位数组,只能定义成结构体或者联合。而且,_Bool变量会被打包成字节的形式。

编译器会将所有的全局_Bool变量打包成字节形式,存放在.bit section中。局部_Bool变量也会被打包成字节形式。但是_Bool类型的参数会被扩展成一个单字节。

具体的关于位变量的定义和使用可参考如下例子:

定义位变量:

_Bool in_range

_Bool p_valid

char *ptr

使用位变量:

in_range = (value >= 10) &&(value <= 20)

p_valid = ptr/* p_valid is true if ptr not 0 */

if (p_valid &&in_

在使用位变量时,若程序编译时提示如下错误:

#error clnk Debug\example.lkf:1 no default placement for segment .bit

The command: "clnk -l"C:\Program Files\COSMIC\CXSTM8_16K_4.2.10\Lib" -o Debug\example.sm8 -mDebug\example.map -sa Debug\example.lkf " has failed, the returned value is: 1

exit code=1.

实际上是由于,在项目中没有定义.bit section。可按照如下步骤,手工添加.bit section:

打开项目链接配置窗口:Project - Settings - Linker,选择 Input 目录项

ASM(汇编语言)一般指汇编语言(面向机器的程序设计语言)。

汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为橡竖搜符号语言。在汇编语言中,用助记符代替机器指令的 *** 作码,用地址符号或标号代替指令或 *** 作数的地址。

在不同的设备中,汇编语言纤察对应着不同的机器语言指令集,通过汇编过程转换成机器指令。特定的汇编语言和特定的机器语言指令集是一一对应的,不同平台之间不可直接移植。

汇编语言对比高级语言区别

汇编语言的特点是容易被计算机识别和执行,使用它进行编程可以减少占用空间、提高运行速度,并能直接对硬件实施控制。在需要实时控制的时候,有着不可替代的重要地位,但汇编语言在编程和理解时要复杂、困难一些,尤其是在进行数据处理或是逻辑运算时更加凸显出其劣势。

高级语言是面向使用者的语言,能更准确地被程序员所理解,它的表达能力强,功能多,编程效率高梁历,上手速度快, 自动化程度高,因而更受欢迎。

在大部分软件开发中,使用者都采用高级语言编程,以提高编程效率。但在要求存储空间小,执行速度快,需直接对硬件进行控制的场合,则应用汇编语言编程,以达到优化程序速度的目的。

前些天,看到这个标题,直接过了,因为这个好像根本不是问题,结果过了几天,看这个问题还没有结果,于是好奇,进来看看。

RadASM只是一个开发环境,具体使用什竖者么语言,你要有那个语言的编译和链接器,放在任何目录都可以,然后在对应那个语言的xxxx.ini中指定编译器和连接器的位置,如果是MASM宏汇编,那么需要在MASM.INI中指定,例如:

[Enviroment]

1=path,c:\masm32\bin

[CharTab]

2=025122252222223220-2F

3=111111111124222130-3F

[Open]

0="汇编源文件 (*.asm*.inc*.mac*.txt),*.asm*.inc*.mac*.txt"

1="资源文件 (*.rc),*.rc"

2="文本文件 (*.txt),*.txt"

3="所有文件 (*.*),*.*"

src="汇编文件 (*.asm),*.asm,asm"

hdr="头文件 (*.inc),*.inc,inc"

mod="模块 (*.asm*.mac),*.asm*.mac"

1=path 这个就是用来定义宏汇编编译器的地址,填上正确的地址即可。

至于汇编源程序,你完全可以如在DOS环境下使用的那样,例如:

.data

s1   db  '这里放数据‘,0

.code

entry proc

mov  eax, [eax].PEB.ImageBaseAddress

call  GetCurrAddr

mov hInstance[ebx], eax

......

entry endp

.data

s2  db '这里也放数据,当然也可以放到前面去。

.code

start:

  mov   dest, offset Mz

  mov   clenth, Len

invoke GetCurrentDirectory,nBufLen, addr szFName

  invoke lstrcat,addr szFName, addr myFName

invoke CreateFile,addr szFName,       pointer to name of the file

          GENERIC_WRITE or GENERIC_READ,access (read-write) mode

          null,                         share mode

          null,                         pointer to security attributes

          CREATE_ALWAYS,          轮羡      how to create

          FILE_ATTRIBUTE_NORMAL,        file attributes

          NULL

mov hFile, eax

  invoke WriteFile,hFile,dest,clenth,addr br,NULL

.if eax

    invoke lstrcpy,addr szFName,addr myFName1

    invoke lstrcat,addr szFName,addr szOpenOk

    invoke MessageBox,null,addr szFName,

            addr szCaption,MB_OK

  .else

    invoke MessageBox,NULL,addr szOpenEr,

            addr szCaption,MB_ICONERROR or MB_OK

  .endif

invoke CloseHandle,hFile

  xor eax, eax

 余桐薯 invoke ExitProcess,eax

end start

编译链接后,代码从 start开始执行,start 的级别比 entry 高,如果代码中有entry,同时有start,那么编译后,结果是start,而不是entry,准确的说法是结尾 end 后面根的启动地址名称,随便叫什么都可以,习惯上用 start。

这是我以前写书时写的一些演示代码,都是在RadASM中开发的,代码绝对都可以编译运行的,我在附件里给你发一个汇编源代码,你可以试着用RadASM来编译一下。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/12314118.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存