汇编语言c equ a-b,C语言和汇编语言对比-Go语言中文社区

C语言中,程序员所定义的每一个变量,不管是基本类型(char,unsigned char,int unsigned int,short,unsigned short,long,unsigned long,double)的变量还是构造类型(数组,struct,enum,union,链表等)的变量,在编译之后都安排在了内存中的特定存储区域里面了, 每一个变量都对应特定的内存空间。

汇编语言中,根本就没有变量的说法,程序员所面对的就是赤裸裸的存储空间,可能是RAM,可能是EEPROM,还可能是FLASH,程序员需要自己给这些存储空间命名(相对于C语言,汇编语言完全需要自己分配内存),然后直接进行访问(读操作或者写操作)。例如在RAM空间中给地址为$100的存储单元命名,然后清空它的值,接着把I2C数据寄存器中的值读取到该存储单元中,接着再对该值自加1,最后将它的值保存到EEPROM的某个存储单元和FLASH的某个存储单元中。代码如下:

stm8/

#include "mapping.inc"

#include "stm8s103f.inc"

;ram的存储空间为$0000~$03FF

;在ram存储空间中地址为$100的存储单元命名为data_ram

data_ram EQU $100  ;用data_ram代表地址为$100的存储单元

;eeprom的存储空间为$4000~$427F

;在eeprom存储空间中地址为$4001的存储单元命名为data_eeprom

data_eeprom EQU $4001

;flash的存储空间为$8080~9FFF

;在flash存储空间中地址为$9000的存储单元命名为data_flash

data_flash EQU $9000

; I2C Bus Interface (I2C) at 0x5210

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.I2C_CR1DS.B 1; I2C control register 1

.I2C_CR2DS.B 1; I2C control register 2

.I2C_FREQRDS.B 1; I2C frequency register

.I2C_OARLDS.B 1; I2C Own address register low

.I2C_OARHDS.B 1; I2C Own address register high

reserved13DS.B 1; unused

.I2C_DRDS.B 1; I2C data register

; Flash at 0x505a

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.FLASH_CR1DS.B 1; Flash control register 1

.FLASH_CR2DS.B 1; Flash control register 2

.FLASH_NCR2DS.B 1; Flash complementary control register 2

.FLASH_FPRDS.B 1; Flash protection register

.FLASH_NFPRDS.B 1; Flash complementary protection register

.FLASH_IAPSRDS.B 1; Flash in-application programming status register

reserved2DS.B 2; unused

.FLASH_PUKRDS.B 1; Flash Program memory unprotection register

reserved3DS.B 1; unused

.FLASH_DUKRDS.B 1; Data EEPROM unprotection register

reserved4DS.B 59; unused

; Independent Watchdog (IWDG) at 0x50e0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

.IWDG_KRDS.B 1; IWDG Key Register

.IWDG_PRDS.B 1; IWDG Prescaler Register

.IWDG_RLRDS.B 1; IWDG Reload Register

reserved10DS.B 13; unused

;----------------------------------------

;----------------------------------------

segment 'rom'

main.l

CLR data_ram ;72 5F 01 00

LD A,I2C_DR ;C6 52 16

LD data_ram,A ;C7 01 00

INC data_ram ;72 5C 01 00

CALL UnkeyprocessEep

CALL unkeyprocessFla

JRA main ;20 XX/20 A8

TAB1.L

DC.B $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F

UnkeyprocessEep.L

MOV FLASH_DUKR,#$AE ;35 AE 50 64

NOP ;9D

MOV FLASH_DUKR,#$56 ;35 56 50 64

MOV IWDG_KR,#$AA ;35 AA 50 E0

BTJF FLASH_IAPSR,#3,UnkeyprocessEep ;72 0n MS LS XX /72 07 50 5F EE

UnkeyprocessendEep.L

LD A,data_ram ;C6 01 00

LD data_eeprom,A ;C7 40 01

MOV IWDG_KR,#$AA ;35 AA 50 E0

BTJF FLASH_IAPSR,#2,UnkeyprocessendEep ;72 05 50 5F F1

RET

TAB2.L

DC.B $00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$AA,$BB,$CC,$DD,$EE,$FF

unkeyprocessFla.L

MOV FLASH_DUKR,#$AE ;35 AE 50 64

NOP ;9D

MOV FLASH_DUKR,#$56 ;35 56 50 64

MOV IWDG_KR,#$AA ;35 AA 50 E0

BTJF FLASH_IAPSR,#3,unkeyprocessFla ;72 07 50 5F EE

UnkeyprocessendFla.L

LD A,data_ram ;C6 01 00

LD data_flash,A ;C7 90 00

MOV IWDG_KR,#$AA ;35 AA 50 E0

BTJF FLASH_IAPSR,#2,UnkeyprocessendFla ;72 07 50 5F F1

LD data_flash,A ;C7 90 00

RET

interrupt NonHandledInterrupt

NonHandledInterrupt.l

iret ;80

segment 'vectit'

dc.l {$82000000+main}; reset

dc.l {$82000000+NonHandledInterrupt}; trap

dc.l {$82000000+NonHandledInterrupt}; irq0

dc.l {$82000000+NonHandledInterrupt}; irq1

dc.l {$82000000+NonHandledInterrupt}; irq2

dc.l {$82000000+NonHandledInterrupt}; irq3

dc.l {$82000000+NonHandledInterrupt}; irq4

dc.l {$82000000+NonHandledInterrupt}; irq5

dc.l {$82000000+NonHandledInterrupt}; irq6

dc.l {$82000000+NonHandledInterrupt}; irq7

dc.l {$82000000+NonHandledInterrupt}; irq8

dc.l {$82000000+NonHandledInterrupt}; irq9

dc.l {$82000000+NonHandledInterrupt}; irq10

dc.l {$82000000+NonHandledInterrupt}; irq11

dc.l {$82000000+NonHandledInterrupt}; irq12

dc.l {$82000000+NonHandledInterrupt}; irq13

dc.l {$82000000+NonHandledInterrupt}; irq14

dc.l {$82000000+NonHandledInterrupt}; irq15

dc.l {$82000000+NonHandledInterrupt}; irq16

dc.l {$82000000+NonHandledInterrupt}; irq17

dc.l {$82000000+NonHandledInterrupt}; irq18

dc.l {$82000000+NonHandledInterrupt}; irq19

dc.l {$82000000+NonHandledInterrupt}; irq20

dc.l {$82000000+NonHandledInterrupt}; irq21

dc.l {$82000000+NonHandledInterrupt}; irq22

dc.l {$82000000+NonHandledInterrupt}; irq23

dc.l {$82000000+NonHandledInterrupt}; irq24

dc.l {$82000000+NonHandledInterrupt}; irq25

dc.l {$82000000+NonHandledInterrupt}; irq26

dc.l {$82000000+NonHandledInterrupt}; irq27

dc.l {$82000000+NonHandledInterrupt}; irq28

dc.l {$82000000+NonHandledInterrupt}; irq29

end

上面的汇编代码被汇编器编译为如下的二进制机器码:

849a86d31346051f1f80cefd38f982b0.png

最上面地址为8000~807F的区域为中断向量表;下边最左边绿框为对应单片机FLASH的地址;中间对应真正的机器码;右边框对应机器码的ASCLL码值。

我们拿data_ram为例进行说明,站在C语言的角度来讲,data_ram其实就是一个变量,CLR data_ram其实就是将该变量清零;但是站在汇编语言角度来讲,它就代表了一个地址,这个地址就是0x0100,于是CLR data_ram最终生成的机器码就是72 5F 01 00,单片机CPU取出这个指令后就会把地址0x0100处的存储单元清零。另外为了说明常数是怎么存储的,我拿下面两个常熟表进行说明:

TAB1.L

DC.B $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0A,$0B,$0C,$0D,$0E,$0F

TAB2.L

DC.B $00,$11,$22,$33,$44,$55,$66,$77,$88,$99,$AA,$BB,$CC,$DD,$EE,$FF

这两个表的数值直接跟代码一起混合放在了代码存储区,由于CPU执行代码完全是根据PC寄存器指定的地址进行的,而PC寄存器是不会指向上面的这两个表的,也就是说上面这两个表是不会当做代码执行的,比如CALL UnkeyprocessEep这条指令中标号UnkeyprocessEep就会跳过TAB1,而直接找到子程序UnkeyprocessEep处。

汇编器生成机器码之后会组织成一个文件,这个文件可以是.bin格式的,可以是.hex格式的,可以是.s19格式的,可以是sx格式的,还可以是eep格式的,它们并不是直接把赤裸裸的机器码放在上面,而是基于特定的规范增加了前缀和后缀,最终下载到单片机内部FLASH的时候就会对其进行解码,生产赤裸裸的机器码,存放到单片机FLASH中。以S19格式为例,下图就是S19文件转为机器码再下载到FLASH中的过程:

011f05fcd7f331f8ad03af81993027e0.png

如果上面代码用C语言描述就是:

//宏定义,下面就可以直接对一个地址读写操作

#define I2C_DR (*(uint8_t *)0x5216)

#define FLASH_DUKR (*(uint8_t *)0x5064)

#define IWDG_KR (*(uint8_t *)0x50E0)

#define FLASH_IAPSR (*(uint8_t *)0x505F)

#define data_eeprom (*(uint8_t *)0x4001)

#define data_flash (*(uint8_t *)0x9001)//要保证0x9001并没有被代码占用

//定义一个usigned char类型的变量data_ram

uint8_t data_ram;

//把I2C数据寄存器中的值搬运到data_ram存储单元中

data_ram=I2C_DR;

//eeprom解锁

do

{

FLASH_DUKR=0xae;

Delayus(1);

FLASH_DUKR=0x56;

IWDG_KR=0xaa;

}while(0==FLASH_IAPSR&(1<<3);

//把数据保存到eeprom中

data_eeprom=data1+1;

//flash解锁

do

{

FLASH_DUKR=0xae;

Delayus(1);

FLASH_DUKR=0x56;

IWDG_KR=0xaa;

}while(0==FLASH_IAPSR&(1<<3);

//把数据保存到flash中

data_flash=data_ram+1;

从上面的汇编代码和C语言代码可以很明显的看出,C语言代码中有些东西是由编译器处理的,比如全局变量data_ram内存空间分配,编译器遇到uint8_t  data_ram;之后就会在RAM中给它安排一个存储单元,这个存储单元的地址是固定不变的,而这其实就是分配好了变量data_ram的存储空间。

74a02924d61121f17985d60a59796fde.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值