Skip to content

CrystalGrape/assembly-n

Repository files navigation

assembly-n 使用向导

#简介:

assembly-n是基于C++的虚拟机,在虚拟机上可以直接运行assembly-n汇编语言,未来assembly-n将作为program-n的中间语言。在本文中assembly-n简称为asn。

一、使用assembly-n


1、在Windows平台上使用

  1. 下载assembly-n源码
  2. 使用vs2015打开工程(如果是其他版本的vs,可以在工程属性里修改平台工具集)。
  3. 编译。
  4. 使用assembly-n [namespace]运行asn。

2、在Linux平台上使用

  1. git clone https://github.com/CrystalGrape/assembly-n
  2. 编译ExternalCall.cpp:g++ -c ExternalCall.cpp -DLINUX
  3. make
  4. 使用assembly-n [namespace]运行asn。

二、使用asn汇编


1、指令格式

一条asn指令由指令部分和参数部分组成。指令部分是必须存在的部分;不同指令具有不同个数的参数,但是指令至少0个,至多三个,参数与参数间用逗号分隔.

asn指令格式:opcode [arg1],[arg2],[arg3]

2、参数类型

asn有三种参数类型,分别是:立即数、指针、寄存器

1、立即数是一个常数,不加任何修饰,如:mov r0,89,89就是一个立即数。
2、指针是一个指向内存的地址,在立即数前加#表示这个数是一个指针,如:mov r0,#100,#100就是指向内存地址为100的指针。
3、寄存器是虚拟机内定义的所有寄存器,目前总共有15个寄存器,各寄存器如下表所示:
**注意:**事实上由于指令判断的方式,立即数和指针在大多时候都可以混用。

       
寄存器 功能
R0 通用寄存器
···
R9
PC或R10 程序计数器
lr或R11 连接寄存器
sp或R12 栈寄存器
dptr或R13指针寄存器
(已经废除,可以作为通用寄存器使用,
在program-n中作为临时变量堆栈指针使用)
cpsr或R14 状态寄存器
## 3、指令集 ## >asn目前包括22个指令,基本上能够满足简单的需求,后续会根据需求添加指令集
序号 指令 使用方式
1 mov 数据转移指令
2 str 数据存储指令
3 ldr 数据加载指令
4 push 数据入栈指令
5 pop 数据出栈指令
6 jmp 无条件跳转指令
7 cjmp 条件跳转指令
8 bjmp 带返回跳转指令
9 ret 返回指令
10 end 程序结束指令
11 add 加法指令
12 sub 减法指令
13 mul 乘法指令
14 gt 大于判断指令
15 gte 大于等于判断指令
16 lt 小于判断指令
17 lte 小于等于判断指令
18 entry 加载动态库指令
19 call 调用动态库指令
20 exit 卸载动态库指令
21 strb 字节存储指令
22 strb 字节加载指令
## 4、使用指令 >首先约定:rn表示任意寄存器,#ptr表示指针,data表示立即数,sectionFlag是段标志。

(1) mov指令

mov rn,[rn,#ptr,data]
将参数二表示的数据写入参数一。
参数一必须是寄存器,参数二可以为任意类型数据。

(2) str指令

str rn,[rn,#ptr,data]
将参数一中的数据写入到参数二指向的内存中。
参数一必须是寄存器,参数二可以为任意类型数据。

(3) ldr指令

ldr rn,[rn,#ptr,data]
将参数二指向的内存空间中的数据加载到参数一中。
参数一必须是寄存器,参数二可以为任意类型数据。

(4) push指令

push rn
将参数一压入到栈顶。
参数一必须是寄存器。

(5) pop指令

pop rn
将栈顶数据出栈到参数一中。
参数一必须是寄存器。

(6) jmp指令

jmp sectionFlag
无条件跳转到参数一指向的段。
参数一是段标志。

(7) cjmp指令

cjmp sectionFlag
首先判断cpsr的溢出标志,如果溢出则跳转到参数一指向的段。
参数一是段标志。

(8) bjmp指令

bjmp sectionFlag
带返回的跳转指令,与ret配合使用。
参数一是段标志。

(9) ret指令

ret
返回到链接寄存器指向的指令,与bjmp配合实现函数功能。

(10) end指令

end
程序结束指令,运行到此处程序退出。

(11) add指令

add rn,rn,rn
将参数二与参数三相加,结果存储到参数一中。
三个参数都必须是寄存器。

(12) sub指令

sub rn,rn,rn
将参数二与参数三相减,结果存储到参数一中。
三个参数都必须是寄存器。

(13) mul指令

mul rn,rn,rn
将参数二与参数三相乘,结果存储到参数一中。
三个参数都必须是寄存器。

(14) gt指令

gt rn,rn
判断参数一是否大于参数二,如果大于,将cpsr溢出标志置位。
两个参数都必须是寄存器。

(15) gte指令

gte rn,rn
判断参数一是否大于等于参数二,如果大于等于,将cpsr溢出标志置位。
两个参数都必须是寄存器。

(16) lt指令

lt rn,rn
判断参数一是否小于参数二,如果小于,将cpsr溢出标志置位。
两个参数都必须是寄存器。

(17) lte指令

lte rn,rn
判断参数一是否小于等于参数二,如果小于等于,将cpsr溢出标志置位。
两个参数都必须是寄存器。

(18) entry指令

entry rn
加载动态链接库,参数一是一个地址,地址指向到内存中动态库完全路径的字符串。
参数一必须是寄存器。

(19) call指令

call rn
调用动态链接库中的函数,参数一是一个地址,地址指向到内存中函数名的字符串。
参数一必须是寄存器。

(20) exit指令

exit
释放动态链接库

(21) strb指令

strb rn,[rn,#dptr],[rn,data]
将参数一最低一个字节的数据存储到参数二指向的内存中的第参数三个位置。
参数一必须是寄存器,参数二是寄存器或指针,参数三是立即数或寄存器。

(22) ldrb指令

ldrb rn,[rn,#dptr],[rn,data]
将数据存储到参数二指向的内存中的第参数三个位置的一个字节数据加载到参数一中。
参数一必须是寄存器,参数二是寄存器或指针,参数三是立即数或寄存器。

**注意:**从上面的详细信息可以看出只有在strb和ldrb中指针和立即数才存在区别。

5、模块与段

为了增强asn的模块化能力,asn提供了段和模块来实现模块化。

(1) 段

段是asn中最基本的模块化工具,利用段和三种跳转指令可以实现选择结构、循环结构和函数。

选择结构:

section yes:
	;真分支
	end
lt r0,r1
cjmp yes
;假分支
end

循环结构:

section loop:
	;循环过程
	mov r1,10
	mov r2,1
	add r0,r0,r2
	lt r0,r1
	cjmp loop
	end

函数:

section testfunc:
	;函数过程
	ret
bjmp testfunc
end

(2) 模块

模块是一个独立的asn源文件,模块中最基本的单位是函数,如果在模块中写入非函数代码,这些代码将不可用。一个模块有一个或多个函数组成。利用import指令可以将模块加载到当前模块中。

模块引用:

import后的参数是模块相对于当前模块的相对路径,将路径分隔符('/'或'')替换为‘.’,将后缀省略。

import lib.io

事实上由于模块是直接加载到当前文件的,一般在模块引用之前将程序跳转到入口函数中,如:

jmp main
import lib.io
section main:
	;主程序
	end

**注意:**模块不能重复引用,在一个地方引用后,在程序中所有地方都能使用。

6、注释

目前只支持单行注释,使用逗号作为注释的开始,如:

;注释

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published