1,一些额外的指令:
intmul(整数乘法),,,它的目的操作数必须是寄存器,当源操作数是 常量 时候,intmul允许有3个操作数,intmul只允许有16位和32位的操作数,它不对8位的操作数做乘 法。
bound指令通过对16位,32位的寄存器进行检查来判断他们是否处于两个数之间。
bound(reg16,LBconstant,UBconstant)
bound(reg16,mem16 [2])
mem16[0]<=register<=mem16[2]
如果指定的 寄存器 不在给定的范围内,那么80×86就会引发异常,该异常可以用try。。。endtry异常处理语句来捕获,ex.boundinstr
bound指令实例:
program bounddemo
#include(stdlib.hhf);
static
inputvalue: int32;
goodinput: boolean;
begin bounddemo;
repeat
mov(false,goodinput);
try
stdout.put("enter a integer between 1 and 10: ");
stdin.flushinput();
stdin.geti32();
mov(eax,inputvalue);
bound(eax,1,10);
mov(true,goodinput);
exception(ex.conversionerror)
stdout.put("illegal numeric format,re_enter",nl);
exception(ex.valueoutrange)
stdout.put("tai da le zhe ge shu",nl);
exception(ex.boundinstr)
stdout.put
(
"value is",
inputvalue,
",it must be between 1 and 10,re_enter,"
nl
);
endtry;
until(goodinput);
2,into指令在特定的情况下也会产生异常 ,特别是设置了上溢标志 ,它就会产生异常 ex.intoInstr
program intodemo;
#include("stdlib.hhf")
static
operate: int8;
result: int8;
begin intodemo;
try
stdout.put("enter a small integer value(-128_127);
stdin.geti8();//注意于stdin.get(x)的区别
mov(al,operate);
stdout.put("enter a second small integer value -128....127:");
stdin.geti8();
add(operate,al);
into();
stdout.put("the eight bit number is ",(type int8 al),nl);
exception(ex.valueoutofvalue)
stdout.put(" ");
exception();
stdout.put();
exception(ex.intoInstr);
stdout.put
(
"the sum of the two value is outside the range -128_127",
nl
);
endtry;
end intodemo;
3,HLA常量和数值声明 注意这是常量
HLA中const和val段允许声明符号常量,const段允许声明那些在整个编译和运行过程中值为常量的表识符,val段允许声明那些在编译中可以改变,但是在运行时必须为常量的符号
const
pi: real32 :=3.14159;
maxindex: uns32 :=15;
delimiter: char :'\';
4,,常量类型
字符串和字符字面常量
“a”和‘a’是不同的
hla可以自动的对字符串常量进行连接
''first part of string," "second part of string"与''first part of string,second part of string"相同。
http://baike.baidu.com/link?url=EDOszg19ETP3YGRiVB6BaRcy3kUBkQYa2S77mgZ7mr7satrrzBdLl4tnM7VBzL0E
链接是c中转义字符
hla却不支持,,hla提供了其他的方法将特殊字符插入到字符串常量中去
如何在字符串常量中插入双引号和单引号
方法:在字符串常量中插入两个双引号表示单个双引号,插入两个单引号表示一个单引号
hla还可以对邻接字符串常量和字符常量的任意组合进行连接来组成一个字符串常量:
'1' '2' '3'等于“123”
"he write a" ' " ' "hello world" ' " ' "program as an example"等于"he write a "hello world" program as an example"
hla 还提供例如一种表示字符常量的方法。。#integer—constant 该字符常量的值是由integer-constant指定的ascll码
#13 #$d #%1101
#$22是双引号对应的ascii码
5,const段中的字符串常量和文本常量
const
astringconst: string :="123";
atextconst: text :="123";
mov(atextstring,al);完全合法
mov (astringconst,al);不合法
因为不能将字符串字面常量移动到al寄存器
6,在windows中
const
nl: text :="#$d #$a";
表示nl例如:stdout.put("hello world",nl); nl就是:="#$d #$a";回车 换行
7,常量表达式
符号常量的一般定义: 由一个标示符,一个可选类型,一个字面常量
hla还可以把常量换成常量表达式
如果常量表达式中出现一个表示符,那么该标示符必须是已经在程序中的常量段或者var段定义过的常量标示符
const
x :=5;
y :=6;
sum :=x+y;
运行时候sum=11,这是编译器完成的,而不是cpu
8,val段,val常量和const常量的区别:在于常量的值在编译的时候是否发生改变
const不改变,不必考虑出现在程序的哪个地方
hla的val常量在程序的整个源代码当中可以改变他们的值。。。。val对象在运行时候是常量
一般情况下,val段的声明和赋值只能出现在begin之前,,,但是hla提供了一种机制:“?”操作符,程序中允许出现空格的地方都允许出现 ?声明常量
program demo;
#include("stdlib.hhf)
val
notconstant :=0;
begin demo;
mov(notconstant,rax);
stdout.put("eax=",(type uns32 eax),nl);
?notconstant :=10;
mov(notconstant,eax);
stdout.put("eax=",(type uns32 eax),nl);
end demo;
9,HLA的type段
type
integer: int32;
float: real32;
double: real64;
color: byte;
static:
i: integer;
x: float;
housecolor: color;
记住不要定义一个int型数据,因为在80×86中int是中断,它在HLA中是保留字
10,enum和HLA中的枚举数据类型
type
tapedrives: enum(tapedat ,tape8mm,sdfasda,sdfsdfd,);
static
backhaha: tapedrives :=tapedat;
;
;
;
mov(backhaha,al);
if(al=tape8mm)then
;;;;
endif;
默认情况下,hla为枚举类型保留一个字节的存储空间,backhaha变量占用一个字节的存储空间,可以用8位的寄存器访问
tapedat=0; ,tape8mm=1,sdfasda=2,sdfsdfd=3
6,指针数据类型
指针只是一个存储单元,他存储着另一个存储单元的地址。
HLA指针是一个可以包含其他变量地址的32位的数值
假设p是一个指向双字的指针,
mov(p,ebx);
mov([ebx],eax);
HLA专门为声明指针变量提供了短语pointer to
例子:
static
b: byte;
d: dword;
pbytevar: poiner to byte :=&b;
还可以在hla程序的type段定义自己的指针类型。
type
ptrchar : pointer to char;
static
cstring: ptrchar;
指针常量和指针常量表达式;
program ptrconstdemo;
#include("stdlib.hhf)
static
b: byte :=0;
byte 1,2,3,4,5,6,7;
const
pb:=&b+1;
begin ptrconstdemo;
mov(pb,ebx);
mov([ebx],al);
stdout.put("value at address pb =$",al,nl);
end ptrconstdemo;
这样al最后等于1
指针变量和动态内存分配
mem.alloc函数将他分配的存储区的地址返回给eax寄存器;之后马上使用一个mov指令将地址直接存储到一个指针变量中。
指针常见的问题:
1,使用没有初始化的指针
static:
b: byte;
d: dword;
haha: pointer to byte;
begin chengxu:
mov(haha,ebx);
mov([ebx],al);
stdout.put(" ",al,nl);
end chengxu;
虽然静态段中所声明的变量已经被初始化了,但是静态初始化仍然不会为程序中的指针分配一个有效的地址(他将指针初始化为0,也就是null)
2,使用具有非法的指针例如(null)
3,悬空指针 在存储区释放后仍然使用mem.aloc分配的存储区
4,在程序使用完之后没有使用mem.free释放
5,使用错误的数据类型访问间接数据。。。。。。
program haha;
#include(" stdlib.hhf)
static
ptr: pointer to char ;
cnt: uns32;
begin haha;
mem.alloc(256);
mov(eax,ptr);
stdout.put(" enter a line of text:"5);
stdin.flushinput();
mov(0,cnt);
mov(ptr,ebx);
repeat
stdin.getc();
mov(al,[ebx]);
inc(cnt);
inc(ebx);
until(stdin.eoln());
mov(ptr,ebx);
for(mov(cnt,ecx);ecx>0;dec(ecx))do
mov([ebx],eax);
stdout.put(" ",eax,nl);
inc(ebx);
endfor;
mem.free(ptr);
end haha;
6,复合数据类型
字符串
hla支持以0结尾的字符串
static:
hahastring: char; @nostorage;
byte " this is the zero-terminated string ",0;
hla也支持zstring数据类型,,,这些对象是 字类型
static:
hahastring: char; @nostorage;
byte " this is the zero-terminated string ",0;
zstrvar: zstring :=&hahastring;
以0结尾的字符串的缺点是计算长度效率低下