Freescale 汇编语言源程序标准
------------------------------------------------------
此标准包括:
行的长度限制
可接受的字符和字符格式
源程序列的分配
注释格式
-------------------------------------------------------
行的长度:
为了便于阅读和打印,Freescale使用mono-spaced字体,这种字体每个字符宽度相等.字体大小是9 point;最大行长为70个字符.
示例如下:
; 1 2 3 4 5 6 7
;234567890123456789012345678901234567890123456789012345678901234567890
asc2hex: bsr ishex ;check for valid hex # first
bne dunA2asc ;if not just return
cmp #’9’ ;check for A-F ($41-$46)
bls notA2F ;skip if not A-F
列表输出文件示例如下:
; 1 2 3 4 5 6 7 8 9
;23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123
551 C1D7 AD EA asc2hex: bsr ishex ;check for valid hex # first
552 C1D9 26 0A bne dunA2asc ;if not just return
553 C1DB A1 39 cmp #’9’ ;check for A-F ($41-$46)
554 C1DD 23 02 bls notA2F ;skip if not A-F
从以上可以看出列宽最大到93字符,因为列表输出文件并不能给读者提供更多的有用信息,因此Freescale最大用到每行93字符.
-----------------------------------------------------------
避免使用TAB字符
TAB字符在不同的字处理软件中有不同的含义,当把源文件提交给其它文档时可能会出现问题,所以要避免使用TAB,而用多个空格代替.
-----------------------------------------------------------
源程序列分配
源程序由标号,助记符,操作数和注释组成一行;
标号在第1列开始
指令助记符在第13列开始
操作数在19列开始
注释在31列开始;如果操作数超过了30列,注释必须和操作数的最后一个字符分开1到2个空格.
如果一个标号超过11个字符,就应该另起一行,并在31列做注释.短标号也可以另起一行来突出它,这经常用在一个子程序开始处.见图3
; 1 2 3 4 5 6 7
;234567890123456789012345678901234567890123456789012345678901234567890
label: mne operand ;comment
brset very,long,operand ;comment can’t start in col 31
veryLongLabel: ;long label on separate line
nop ;instruction with no operands
short: ;short label may use a separate line
mne operand ;code to which ‘short’ refers
-----------------------------------------------------------
大写和小写字符
源程序中协调一致的大小写可以增强可读性,并使程序变得容易理解.
标号
标号可以混和使用大小写,但无论在哪儿引用它都应该严格匹配其初始定义.
指令助记符
指令助记符,汇编指示和预处理应当使用小写字符.尽管他们可以使用大写字符,但是输入时要敲shift键,而且大写字符使读者变得不能专心阅读.
各种各样得文档中指令使用大写字符仅仅是为了突出他们.有经验得程序员使用小写字符不但容易输入而且容易阅读.
寄存器和位
Freescale的头文件中使用大写字符定义寄存器和位.位的定义有两种方法位号(0-7)和位屏蔽码.位操作指令使用位号;逻辑操作指令使用屏蔽码方式.屏蔽码在位号前面加一个小写字母m前缀.示例见图4
PTAD: equ $00 ;I/O port A data register
; bit numbers for use in BCLR, BSET, BRCLR, and BRSET
PTAD7: equ 7 ;bit #7
PTAD6: equ 6 ;bit #6
PTAD5: equ 5 ;bit #5
PTAD4: equ 4 ;bit #4
PTAD3: equ 3 ;bit #3
PTAD2: equ 2 ;bit #2
PTAD1: equ 1 ;bit #1
PTAD0: equ 0 ;bit #0
; bit position masks
mPTAD7: equ %10000000 ;port A bit 7
mPTAD6: equ %01000000 ;port A bit 6
mPTAD5: equ %00100000 ;port A bit 5
mPTAD4: equ %00010000 ;port A bit 4
mPTAD3: equ %00001000 ;port A bit 3
mPTAD2: equ %00000100 ;port A bit 2
mPTAD1: equ %00000010 ;port A bit 1
mPTAD0: equ %00000001 ;port A bit 0
-----------------------------------------------------------
标号
标号可以混和使用大小写,但避免使用下划线,我们推荐使用大写字符做为多字符标号的分界.例如:VeryLongLabel代替ery_long_label
标号定义并加一个冒号,尽管有很多编译器不需要这个冒号.
文件和子程序头
文件和子程序前面需要一个块来说明他的用途和目的,称为头
图5是典型的文件头
;********************************************************************************************
;* Title: 9S08GB60_v1r2.equ (c) FREESCALE Inc. 2003 All rights reserved.
;********************************************************************************************
;* Author: Jim Sibigtroth - Freescale TSPG
;*
;* Description: Register and bit name definitions for 9S08GB60
;*
;* Documentation: 9S08GB60 family Data Sheet for register and bit explanations
;* HCS08 Family Reference Manual (HCS08RM1/D) appendix B for explanation of equate files
;*
;* Include Files: none
;*
;* Assembler: Metrowerks Code Warrior 3.0 (pre-release)
;* or P&E Microcomputer Systems - CASMS08 (beta v4.02)
;*
;* Revision History:
;* Rev # Date Who Comments
;* ----- ----------- ------ --------------------------------------------
;* 1.2 24-Apr-03 J-Sib correct minor typos in comments
;* 1.1 21-Apr-03 J-Sib comments and modify for CW 3.0 project
;* 1.0 15-Apr-03 J-Sib Release version for 9S09GB60
;********************************************************************************************
其中有些是必须的,有些可以省略
文件名:必须,包括文件名和后缀
版权声明:必须
作者:必须,有些文件可能重复使用数年,有时需要帮助时可以联系他们
描述:必须,但仅是摘要,更多信息应该在一个单独的文件中
文档:另外一个文件,她是对这个文件的详细说明
包含文件:需要时必须
汇编器:汇编器的厂商和版本,非常重要
版本历史:提供何时,何人,哪个文件被修改等信息
图6是子程序头模板,可以根据子程序的复杂程度适当增减
;******************************************************************
;* RoutineName - expanded name or phrase describing purpose
;* Brief description, typically a few lines explaining the
;* purpose of the program.
;*
;* I/O: Explain what is expected and what is produced
;*
;* Calling Convention: How is the routine called?
;*
;* Stack Usage: (when needed) When a routine has several variables
;* on the stack, this section describes the structure of the
;* information.
;*
;* Information about routines that are called and any registers
;* that get destroyed. In general, if some registers are pushed at
;* the beginning and pulled at the end, it is not necessary to
;* describe this in the routine header.
;******************************************************************
;******************************************************************
;* GetSRec - retrieve one S-record via SCI1
;* Terminal program should delay after to allow programming
;* recommended delay after is TBDms, no delay after chars.
;* Only header (S0), data (S1), and end (S9) records accepted
;*
;* Calling Convention:
;* ais #-bufferLength ;# of data bytes + 4 (typ.36)
;* jsr GetSRec ;read S-record onto stack
;* bne error ;Z=0 means record bad
;*;
;*; ’bufferLength’ is defined in calling program not in this
;*; subroutine, calling routine must also deallocate buffer space
;*; after processing the information that was returned on the stack
;*;
;* ais #bufferLength ;deallocate buffer space
;*
;* Returns: all but CCR Z-bit returned on stack (see stack map)
;* CCR Z-bit = 1 if valid S-record; CCR Z-bit = 0 if not valid
;* S-record type @ sp+1 (1 ASCII byte) ($30, $31, or $39)
;* S-record size @ sp+2 (1 hex byte) (# of data bytes 0-31)
;* S-record addr @ sp+3 (2 hex bytes) (addr of 1st data value)
;* S-record data @ sp+5..sp+36 (up to 32 hex data bytes)
;*
;* Stack map... S-record, return, and locals on stack
;* | | <-sp (after local space allocated)
;* H:X-> | SRecCount |
;* | SRecChkSum | <-sp (after jsr)
;* | ReturnAddr msb |
;* | ReturnAddr lsb | <-sp (after rts)
;* | SRecTyp |
;* | SRecSize |
;* H:X-> | SRecAddr msb |
;* | SRecAddr lsb |
;* | SRecData 00 |
;* | SRecData 01 | etc... (up to 32 bytes)
;*
;* Data values are read as two ASCII characters, converted to
;* hex digits, combined into 1 hex value, and stored on stack
;*
;* Calls: GetChar, PutChar, and GetHexByte
;* Changes: A, H, and X
;******************************************************************
图7是一个复杂的头,它使用堆栈传递参数并且附加的堆栈来分配局部变量.虽然可以描述很多的细节但我们规定头的描述最好限制在3到4行.如果要求更多的细节,可以使用一个的单独的文件,而不是描述在代码文件中.
调用协议是想当复杂的,因为用户必须分配传递参数的堆栈空间,堆栈内的参数包括用户填充的和本子程序返回的.当这个子程序放回后,一条BNE指令用来检查Z标志来检查本子程序是否成功得到一个S记录.当检查到一个错误或可处理的返回数据,调用程序必须处理调用前分配的传递参数的堆栈空间.
堆栈的用法也非常复杂,因为本子程序在堆栈上处理信息,所以给读者提供一个堆栈信息映像来帮助读者理解这个子程序是非常重要的.这个映像展示了一个最大的块,这个块是在调用子程序之前分配的.返回地址做为JSR指令的结果也存储在堆栈上.本子程序内部分配使用的2字节局部变量必须在返回调用程序之前处理完毕.
在这个子程序的头的最后
调用项:列出本子程序需要调用的子程序.
改变项:列出执行本子程序改变的寄存器
;******************************************************************
;* GetChar - wait indefinitely for a character to be received
;* through SCI1 (until RDRF becomes set) then read char into A
;* and return. Reading character clears RDRF. No error checking.
;*
;* Calling convention:
;* jsr GetChar
;*
;* Returns: received character in A
;******************************************************************
图8展示一个简单的子程序头,这个头不包含堆栈信息,也不调用其它子程序,所以这些信息都不需要了.
----------------------------------------------------------------
注释:
注释是非常重要的,大多数注释格式是以分号并从31列开始直到行尾.避免注释重复说明指令内容.
例如:lda pta ;读A口数据.
取而代之注释应传递这样一些信息:为什么指令在这儿,指令如何描述程序功能或系统包含的嵌入式微控制器.
这是一个好的注释:
lda PTAD ;check for low on bit 7 (step switch)
如果注释过长不能在一行完成,那么应该在第1列单独起一行,但不宜频繁使用以防淹没代码行.如果是多行注释可以写成注释块,注释块与代码行以空注释行相分隔如下所示:
;
; In-line comment block. On rare occasions, an extended comment
; is needed to explain some important aspect of a program. Each
; line of the extended comment starts with a semicolon. A line
; with nothing but a semicolon in column 1 is used above and
; below the block comment to set it apart from code.
;
注释格式基础理论
注释或空行可以使程序组成逻辑段以提高可读性.子程序头块可以标识一个子程序的开始.类似的分隔也是非常有用的.
阅读(1132) | 评论(0) | 转发(0) |