微机原理与接口技术 第三章: 汇编语言程序设计

45
微微微微微微微微微 微微微微微微微微微微微 主主主 主主主主 主主主主主主主主主主

Upload: sawyer-simon

Post on 02-Jan-2016

178 views

Category:

Documents


3 download

DESCRIPTION

微机原理与接口技术 第三章: 汇编语言程序设计. 主讲人:鞠 雷 山东大学 计算机科学与技术学院.  内容提要. 汇编语言源程序格式. 文件类型. 扩展名. 汇编语言文件. . s. C 语言源文件. . c. C++ 源文件. . cpp. 引入文件. . INC. 头文件. . h. ARM 源程序文件. .h 文件给出函数和变量的声明 . .c 文件给出函数的定义. 使用简单的文本 编辑器或者其他 的编程开发环境 进行编辑. 引入其他程序中的变量或函数 , 在本程序使用. Arm 源程序汇编连接过程:. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 微机原理与接口技术 第三章: 汇编语言程序设计

微机原理与接口技术 第三章:汇编语言程序设计微机原理与接口技术

第三章:汇编语言程序设计

主讲人:鞠 雷

山东大学 计算机科学与技术学院

Page 2: 微机原理与接口技术 第三章: 汇编语言程序设计

2

 内容提要 内容提要

汇编语言源程序格式

Page 3: 微机原理与接口技术 第三章: 汇编语言程序设计

3

ARM 源程序文件 ARM 源程序文件

使用简单的文本 编辑器或者其他 的编程开发环境 进行编辑 .

文件类型 扩展名

汇编语言文件 .s

C 语言源文件 .c

C++ 源文件 .cpp

引入文件 .INC

头文件 .h

引入其他程序中的变量或函数 ,在本程序使用 .

.h 文件给出函数和变量的声明 ..c 文件给出函数的定义 .

Page 4: 微机原理与接口技术 第三章: 汇编语言程序设计

Arm 源程序汇编连接过程:

例 armasm hello.s

armlink hello.o -o hello.axf

armsd -exec hello.axf ;

armcc -g hello.s -o hello.axf

Page 5: 微机原理与接口技术 第三章: 汇编语言程序设计

汇编语言源程序格式汇编语言源程序格式

汇编语言程序的结构1

汇编语言的行构成2

伪指令3

Page 6: 微机原理与接口技术 第三章: 汇编语言程序设计

1. 汇编语言程序的结构1. 汇编语言程序的结构汇编源程序示例第一部分 (test0 源程序 )

CODE32 ;32 位的 ARM 指令段 AREA codesec, CODE, READONLY ; 代码段,名称 codesec, 属性为 ; 只读main PROC ; 函数 main

STMFD sp!,{lr} ; 保存返回地址到数据栈 ADR r0,strhello ; 取标签 strhello 的地址 BL _printf ; 调用 C 运行时库的 _printf 函数 ; 打印“ Hello world!” 字符串 BL welcomefun ; 调用子函数 welcomfun

LDMFD sp!,{pc} ; 返回调用函数strhello ;strhello 代表本地字符串的地址 DCB "Hello world!\n\0" ; 定义一段字节空间 ENDP ; 函数 main 结束

ARM 的汇编语言程序 一般由几个段组成, 每个段均由 AREA 伪操 作定义。

段可以分为多种,如代码段、数据段、通用段,每个段又有不同的属性,代码段的默认属性为 READONLY ,数据段的默认属性为 READWRITE 。

本程序定义了两个段,第一个段为代码段 codesec ; 多个代码段的情况,一个源文件只能含一个代码段并单独编译,多

个代码段分别编译最后连接成映象文件。可执行映象文件的构成: 一个或多个代码段,代码段的属性为只读。 零个或多个包含初始化数据的数据段,数据段的属性为可读写。 零个或多个不包含初始化数据的数据段,数据段的属性为可读写。

在 ARM ( Thumb )汇编语言程序中,以程序段为单位组织代码。 用 AREA 伪指令定义一个段,并说明所定义段的相关属性 .

段是相对独立的指令或数据序列,具有特定的名称。 段分为代码段和数据段,代码段的内容为执行代码,数据段存放代码运行时需要用到的数据。 一个汇编程序至少应该有一个代码段,当程序较长时,可以分割为多个代码段和数据段,多个段在程序编译链接时最终形成一个可执行的映象文件。

Page 7: 微机原理与接口技术 第三章: 汇编语言程序设计

7

1. 汇编语言程序的结构1. 汇编语言程序的结构汇编源程序示例第二部分

welcomefun ; 子函数 welcomfun

STMFD sp!,{lr} ; 保存返回地址到数据栈

ADR r0,adrstrarm ; 取 adrstrarm 的地址放到寄存器 r0 中 LDR r0,[r0,#0] ; 将 strarm 的值放到 r0 中 BL _printf ; 调用 C 运行时库的 _printf 函数打印 ; “Welcom to ARM world!” 字符串 LDMFD sp!,{pc} ; 返回调用函数adrstrarm ;adrstrarm 标签

DCD strarm ; 保存 strarm 的地址 

AREA constdatasec, DATA, READONLY,ALIGN=0

;

本程序定义了两个段,第二个段为数据段 constdatasec

Page 8: 微机原理与接口技术 第三章: 汇编语言程序设计

8

1. 汇编语言程序的结构1. 汇编语言程序的结构汇编源程序示例第三部分

strarm

DCB "Welcome to ARM world!\n\0" ; 存放“ Welcome to ARM

; world!” 字符串 

EXPORT main ; 导出 main 函数供外部调用 ; 引入三个 C 运行时库函数和 ARM 库 IMPORT _main

IMPORT __main

IMPORT _printf

IMPORT ||Lib$$Request$$armlib||, WEAK

END ; 源程序结束

导入 main PROC ENDP, 在本程序使用 .

导入 ARM 库。WEAK ,若导入符号不存在不给出错误信息 .

导出 main 函数供其他程序使用 .

Page 9: 微机原理与接口技术 第三章: 汇编语言程序设计

9

2. 汇编语言的行构成2. 汇编语言的行构成 格式:

[ 标签 ] 指令 / 伪操作 操作数 [; 语句的注释 ]

所有的标签必须在一行的开头顶格写,前面不能留空格,后面不加“ :” ;

ARM 汇编器对标识符的大小写敏感 , 书写标号及指令时字母的大小写要一致;

注释使用“ ;” 符号,注释的内容从“ ;” 开始到该行的结尾结束。

例: Labeladd add r0,r0,r1 ; 加法指令 Str1 SETS “This is a string.”                 ; 给字符串 Str1 赋值

Page 10: 微机原理与接口技术 第三章: 汇编语言程序设计

10

2. 汇编语言的行构成2. 汇编语言的行构成1. 标签:

标签是一个符号,可以代表指令的地址、变量、数据的地址和常数。

一般以字母开头,由字母、数字、下划线组成。

标签不能采用关键字。 标签 ( 标号 ) 代表可执行语句地址。 标号按其作用域可分为段内标号和和段外标号: 段内标号的地址值在汇编时确定。 例 welcomefun 段外标号的地址值在链接时确定。 例 EXPORT main 段外调用: BL main 局部标号,宏中使用的标号称之为局部标号。

Page 11: 微机原理与接口技术 第三章: 汇编语言程序设计

11

2. 汇编语言的行构成2. 汇编语言的行构成

2. 指令/伪操作: 指令 / 伪操作的助记符或者定义符,通知 ARM 的处理器应该

执行什么样的操作或者通知汇编程序伪操作的功能。3. 操作数

由寄存器名、变量名和常量组成的表达式。例 add r0 , r1, r2 x dcd 0x12

Page 12: 微机原理与接口技术 第三章: 汇编语言程序设计

12

2. 汇编语言的行构成2. 汇编语言的行构成伪操作使用的常量:

数字常量(伪操作不加 # ) 十进制数,如 1 、 2 、 123 十六进制数,如 0x123,0xabc 2_1010

字符常量 由单引号及中间的字符组成,包括 C 语言中的转义字符,

如‘ \a’,‘\n’ ( 响铃,换行 ) 字符串常量

由一对双引号及中间的字符串表示,中间也可以使用 C 语言中的转义字符,比如:“ abcdef\a\r\n”

逻辑常量 {TRUE},{FALSE}, 注意带大括号

Page 13: 微机原理与接口技术 第三章: 汇编语言程序设计

13

3. 伪操作3. 伪操作Ø 没有相对应的操作码或者机器码,通常称为伪指令。Ø 作用是为完成汇编程序作各种准备工作的,由汇编程序在源程

序的汇编期间进行处理,仅在汇编过程中起作用 ( 取地址伪指令与其他伪指令有较大区别 ) 。

Ø 有如下几种伪操作:1. 符号定义伪操作 定义一个内存变量。2. 数据定义伪操作 分配连续内存并初始化。定义多个连续内存变

量。 3. 汇编控制伪操作 控制汇编过程。

Page 14: 微机原理与接口技术 第三章: 汇编语言程序设计

14

3. 伪操作3. 伪操作

1. 符号定义伪操作 ( 定义一个内存变量 )

用于定义 ARM 汇编程序中的变量、对变量赋值等。 符号定义有如下几种伪操作:

用于定义局部变量的 LCLA 、 LCLL 、 LCLS (在宏中使用,不讲) 用于定义全局变量的 GBLA 、 GBLL 、 GBLS ; 用于对变量赋值的 SETA 、 SETL 、 SETS ; 局部变量在宏中定义使用!

Page 15: 微机原理与接口技术 第三章: 汇编语言程序设计

15

3. 伪操作3. 伪操作 GBLA 、 GBLL 、 GBLS 伪操作 定义一个汇编程序中的全局变量。 格式: GBLA/ GBLL/ GBLS 变量名

定义一个全局的数字变量,并初始化为 0

定义一个全局的逻辑变量,并初始化为 F

定 义 一 个 全局 字 符 串 变量 , 并 初 始化为空串

全局变量在整个程序范围内变量名必须唯一。

Page 16: 微机原理与接口技术 第三章: 汇编语言程序设计

16

3. 伪操作3. 伪操作

例: GBLA num1 ; 定义一个全局的数字变量 num1 ,初值 0 num1 SETA 0xabcd GBLL l2 ; 定义一个全局的逻辑变量,变 ; 量名为 l2 ,初值为 F l2 SETL {FALSE} ; 将该变量赋值为假 GBLS str3 ; 定义一个全局的字符串变量 str3 ,初值空串。 str3 SETS “Hello!”

Page 17: 微机原理与接口技术 第三章: 汇编语言程序设计

17

3. 伪操作3. 伪操作

III. SETA 、 SETL 、 SETS格式:变量名 SETA/SETL/SETS 表达式

给 一 个 数字 变 量 赋值

给 一 个 逻辑 变 量 赋值

给 一 个 字符 串 变 量赋值

格式中的变量名必须为已经定义过的全局或局部变量,表达式为将要赋给变量的值。

Page 18: 微机原理与接口技术 第三章: 汇编语言程序设计

18

3. 伪操作3. 伪操作

例: GBLA num1 ; 定义全局数字变量 num1 SETA 0x1234 ; 赋值为 0x1234 GBLS str3 ; 定义全局字符串变量 str3 SETS “Hello!” ; 赋值为“ Hello!”

Page 19: 微机原理与接口技术 第三章: 汇编语言程序设计

19

3. 伪操作3. 伪操作2. 数据定义伪操作

分配存储单元,并初始化。 数据定义有如下几种伪指令:

DCB 分配字节DCW/DCWU 分配半字DCD/DCDU 分配字SPACE MAPFIELD

定义多个连续内存变量 .

定义连续内存空间 .

定义内存表 .

Page 20: 微机原理与接口技术 第三章: 汇编语言程序设计

20

3. 伪操作3. 伪操作

I. DCB DCB 用于分配一块字节单元并用伪指令中指定的

表达式进行初始化。 格式:标号 / 变量 DCB 表达式

DCB 可 用“ =” 代替

表达式可以为使用双引号的字 符 串 或 0-255 的数字

例: Array1 DCB 1,2,3,4,5 ; 数组 str1 DCB “Your are welcome !” ; 构造字符串 ; 并分配空间

Page 21: 微机原理与接口技术 第三章: 汇编语言程序设计

21

3. 伪操作3. 伪操作

II. DCW/DCWU 格式:标号 / 变量 DCW/DCWU 表达式

DCW 分配若干个半字存储单元并用表达式值初始化,存储空间半字对齐。

DCWU 功 能 跟DCW 类似,只是分配的字存储单元不严格半字对齐

例:Arrayw1 DCW 0xa,-0xb,0xc,-0xd ; 构造固定数组并分 ; 配半字存储单元

Page 22: 微机原理与接口技术 第三章: 汇编语言程序设计

22

3. 伪操作3. 伪操作

III. DCD/DCDU 格式:标号 / 变量 DCD/DCDU 表达式

分配若干个字存储单元并用表达式初始化,存储空间字对齐。也可用“ &” 代替

DCDU 只是分配的存储单元不严格字对齐

例:Arrayd1 DCD 1334 , 234 , 345435 ; 构造固定数组并分配 ; 字为单元的存储单元Label DCD str1 ; 该字单元存放 str1 的地址

Page 23: 微机原理与接口技术 第三章: 汇编语言程序设计

23

3. 伪操作3. 伪操作

IV. SPACE 格式: 标号 SPACE 表达式

SPACE 用 于 分 配 一 片连续的存储区域并初始化为 0 ,也可用“%”代替

表达式为要分配的字节数

例:

Freespace SPACE 1000 ; 分配 1000 字节的存储空间

Page 24: 微机原理与接口技术 第三章: 汇编语言程序设计

24

3. 伪操作3. 伪操作V. MAP 格式: MAP 表达式 [, 基址寄存器 ]

MAP 定 义 一个 结 构 化 的内 存 表 的 首地址。

表 达 式 可以 为 程 序中 的 标 号或 数 学 表达式

内存表首地址 =

( 基址寄存器 )+ 表达式

MAP 可以与 FIELD 伪操作配合使用来定义结构化的内存表。

例: MAP 0x130 , R2 ; 内存表首地址为 0x130 +R2

Page 25: 微机原理与接口技术 第三章: 汇编语言程序设计

25

3. 伪操作3. 伪操作VI. FILED 格式:标号 FIELD 字节数

定义一个结构化内存表中数据域的的字节数。 可用“ #” 来代替 FILED

FIELD 常与 MAP 配合使用:MAP 定义内存表的首地址FIELD 定义内存表中的各个数据域的字节数并分配存储单元。

Page 26: 微机原理与接口技术 第三章: 汇编语言程序设计

26

3. 伪操作3. 伪操作

例:MAP 0xF10000 ; 定义结构化内存表首地址为 ;0xF10000 count FIELD 4 ; 定义 count 的长度为 4 字

节, ; 位置为 0xF10000 x FIELD 4 ; 定义 x 的长度为 4 字节,位

置 ; 为 0xF10004 y FIELD 4 ; 定义 y 的长度为 4 字节,位

置 ; 为 0xF10008

Page 27: 微机原理与接口技术 第三章: 汇编语言程序设计

27

其他伪操作其他伪操作

1. AREA 格式: AREA 段名 属性,……

AREA 用于定义一个代码段、数据段或者特定属性的段

属性部分表示该代码段 / 数据段的相关属性,多个属性可以用“,”分隔。

常见属性如下:DATA :定义数据段。 CODE :定义代码段。READONLY :表示本段为只读。READWRITE :表示本段可读写。

Page 28: 微机原理与接口技术 第三章: 汇编语言程序设计

其他伪操作其他伪操作

一个汇编程序至少应该包含一个代码段,当程序太长时,也可以将程序分为多个代码段和数据段。

例: AREA test , CODE , READONLY

AREA ||.text||, CODE, READONLY

28

出现非法字符” .”,以” ||” 使其合法化 .

Page 29: 微机原理与接口技术 第三章: 汇编语言程序设计

29

其他伪操作其他伪操作2. CODE16 、 CODE32

格式: CODE16/CODE32

CODE16 伪操作指示编译器后面的代码为16 位的 Thumb 指令

CODE32 伪操作指示编译器后面的代码为32 位的 ARM 指令

在汇编源代码中同时包含 Thumb 和 ARM 指令时,须用 “ CODE32” 和“ CODE16” 伪指令通知编译器其后的指令序列的类型。

“CODE32” 和“ CODE16” 不能对处理器进行状态的切换。

Page 30: 微机原理与接口技术 第三章: 汇编语言程序设计

30

其他伪操作其他伪操作3. ENTRY

格式: ENTRY

ENTRY 用于指定汇编程序的入口。在一个完整的汇编程序中至少要有一个 ENTRY ,也可以有多个。

下面的代码使用了 ENTRY : AREA subrout, CODE, READONLY

ENTRY ; 指定程序入口 start

MOV r0, #10 ; 设置参数 MOV r1, #3

BL doadd ; 调用子函数

Page 31: 微机原理与接口技术 第三章: 汇编语言程序设计

其他伪操作其他伪操作stop MOV r0, #0x18 ;设置软中断输入参数 LDR r1, =0x20026 SWI 0x123456 ; 调用 ARM 软中断返回 ; cpu 控制权交给调试器doadd ADD r0, r0, r1 ;子函数代码 MOV pc, lr ;子函数返回 END ; 源文件结束

31

Page 32: 微机原理与接口技术 第三章: 汇编语言程序设计

32

其他伪操作其他伪操作

4. END 格式: END

END 告诉编译器已经到了源程序的结尾

例:AREA constdata , DATA , READONLY

……

END ; 结尾

Page 33: 微机原理与接口技术 第三章: 汇编语言程序设计

33

其他伪操作其他伪操作

5. EQU 格式:名称 EQU 表达式 [ ,类型 ]

将程序中的数字常量、标号赋予一个等效的名称。

例:num1 EQU 1234 ; 定义 num1 为 1234

addr5 EQU str1+0x50

d1 EQU 0x2400 , CODE32

; 定义 d1 的值为 0x2400,且 ; 该处为 32 位的 ARM 指令

若表达式为 32 位的常量或 32 位地址常量,可以指定表达式的数据类型。有以下三种类型: DATA 表明该地址处为数据区 CODE16 表明该地址处为thumb 指令 CODE32 表明该地址处为 arm指令

Page 34: 微机原理与接口技术 第三章: 汇编语言程序设计

34

其他伪操作其他伪操作6. EXPORT

格式: EXPORT 标号 [,WEAK]

EXPORT 在程序中声明一个全局标号,其他文件中的代码可以引用该标号。用户也可以用GLOBAL 代替EXPORT例:

AREA ||.text|| , CODE , READONLY

main PROC

……

ENDP

EXPORT main ;声明一个可全局引用的函数 main

END

[,WEAK] 可选项若其他文件有同名的标号,则其他文件同名标号优先被引用。

Page 35: 微机原理与接口技术 第三章: 汇编语言程序设计

35

其他伪操作其他伪操作7. IMPORT

格式: IMPORT 标号 [ , WEAK]

通知编译器此标号在当前源文件中使用,但标号是在其他的源文件中定义的。 不管当前源文件是否使用过该标号,这个标号都被加入到当前源文件的符号表中例:

AREA mycode , CODE , READONLY

IMPORT _printf ; 通知编译器当前文件要引用函 ; 数 _printf

END

[ , WEAK]选项表示如果所有的源文件都没有找到这个标号的定义,编译器也不会提示错误信息。 出错时该标号置为 0 。如果这个标号被 B 或 BL 指令引用,则将 B 或 BL 指令替换为NOP 操作。

Page 36: 微机原理与接口技术 第三章: 汇编语言程序设计

36

其他伪操作其他伪操作8. EXTERN

格式: EXTERN 标号 [,WEAK]

通知编译器此标号在当前源文件中使用,但标号是在其他的源文件中定义的。 与 IMPORT 不同的是,如果该标号未被引用,则该标号不被加入到当前文件的符号表中。

例:AREA ||.text|| , CODE , READONLY

EXTERN _printf ,WEAK ; 告诉编译器当前文件要引用标 ; 号 , 如果找不到,则不提示错误END

[ , WEAK]选项表示如果所有的源文件都没有找到这个标号的定义,编译器也不会提示错误信息。 出错时该标号置为 0 。如果这个标号被 B 或 BL 指令引用,则将 B 或 BL 指令替换为NOP 操作。

Page 37: 微机原理与接口技术 第三章: 汇编语言程序设计

37

其他伪操作其他伪操作9. INCBIN

格式: INCBIN 文件名

INCBIN 将一个数据文件或者目标文件包含到当前的源文件中,编译时被包含的文件不作任何变动的存放在当前文件中,编译器从后面开始继续处理。例:

AREA constdata , DATA , READONLY

INCBIN data1.dat ; 源文件包含文件data1.dat

INCBIN E : \DATA\data2.bin ; 源文件包含文件 ;E : \DATA\data2.bin

END

Page 38: 微机原理与接口技术 第三章: 汇编语言程序设计

ARM Procedure Call Standard (APCS)ARM Procedure Call Standard (APCS)

ARM 过程调用规范 一套函数调用者与被调用之间的协议

对寄存器使用的限制。 使用栈的惯例。 在函数调用之间传递 /返回参数。 可以被‘回溯’的基于栈的结构的格式,用来提供

从失败点到程序入口的函数 ( 和给予的参数 ) 的列表。

APCS 不一个单一的给定标准,而是一系列类似但在特定条件下有所区别的标准

牺牲部分的系统性能,提升程序的通用性

Page 39: 微机原理与接口技术 第三章: 汇编语言程序设计

APCSAPCS

子程序间通过寄存器 R0-R3来传递参数,这时,寄存器 R0-R3可以记作 A1-A4 。被调用的子程序在返回前无需恢复寄存器R0-R3 的内容。

在子程序中,使用寄存器 R4-R11来保存局部变量.这时,寄存器 R4-R11 可以记作 V1-V8 。如果在子程序中使用到了寄存器 V1-V8 中的某些寄存器,子程序进入时必须保存这些寄存器的值,在返回前必须恢复这些寄存器的值;对于子程序中没有用到的寄存器则不必进行这些操作。在 Thumb 程序中,通常只能使用寄存器 R4-R7来保存局部变量。

寄存器 R12 用作子程序间 scratch 寄存器(用于保存 SP ,在函数返回时使用该寄存器出栈),记作 ip 。在子程序间的连接代码段中常有这种使用规则。

Page 40: 微机原理与接口技术 第三章: 汇编语言程序设计

APCSAPCS

寄存器 R13 用作数据栈指针,记作 sp 。在子程序中寄存器R13 不能用作其他用途。寄存器 sp 在进入子程序时的值和退出子程序时的值必须相等。

寄存器 R14 称为连接寄存器,记作 lr 。它用于保存子程序的返回地址。如果在子程序中保存了返回地址,寄存器 R14则可以用作其他用途。

寄存器 R15 是程序计数器,记作 pc 。它不能用作其他用途。

Page 41: 微机原理与接口技术 第三章: 汇编语言程序设计

补充习题补充习题

1 、利用全局变量和局部变量声明伪操作及其赋值伪操作,分别定义算术变量、逻辑变量和串变量并为其赋值。

Page 42: 微机原理与接口技术 第三章: 汇编语言程序设计

2 、读懂下面一段程序,子程序 dststr 执行过程中寄存器R0 、 R1 、 R2 中的内容如何变化 ?试分析并给出子程序执行后的结果 (dststr 所存内容 ) 。 AREA StrCopy, CODE, READONLY

ENTRY ; mark the first instruction to call

start

LDR r1, =srcstr ; pointer to first string

LDR r0, =dststr ; pointer to second string

BL strcopy ; call subroutine to do copy

stop

MOV r0, #0x18

LDR r1, =0x20026

SWI 0x123456

Page 43: 微机原理与接口技术 第三章: 汇编语言程序设计

strcopy

LDRB r2, [r1],#1

STRB r2, [r0],#1

CMP r2, #0

BNE strcopy

MOV pc,lr ; Return

AREA Strings, DATA, READWRITE

srcstr DCB "First string - source",0

dststr DCB "Second string - destination",0

END

Page 44: 微机原理与接口技术 第三章: 汇编语言程序设计

44

AREA max_min, CODE, READONLY

ENTRY

ldr r0,=BUFF

LDR R1,[R0];R1=MAX 最大值 MOV R2,R1 ;R2=MIN 最小值 MOV R4,#0 ;counter

BEGIN

LDR R3,[R0]

CMP R3,R1

BLT LESS

MOV R1,R3

LESS

CMP R3,R2

BGT GREAT

MOV R2,R3

Page 45: 微机原理与接口技术 第三章: 汇编语言程序设计

45

GREAT

ADD R0,R0,#4 ;

ADD R4,R4,#1

CMP R4,#9

BNE BEGIN

str r1,max

str r2,min

MOV r0, #0x18

LDR r1, =0x20026

SWI 0x123456

AREA data, DATA, READWRITE

BUFF DCD 0,-1,2,-3,4,5,6,7,9

max dcd 0

min dcd 0

END