这学期学微机原理,顺便学了点汇编,遇到了很多问题,到百度上去求助几乎没人理我,到CSDN来后发现这里的大牛们特别热情,以后就在CSDN扎根了。
下面是我作的一点点笔记(有许多点子还是大牛们告诉我的),如果其中的错误的地方还希望大家指出。马上就得回家了,就不再排版了,以后再修改。
我用的汇编工具是TASM,对于其它的工具可能结果不同 。
(一)、汇编缩写表:
DB:Define Byte(未完)
———————————————————————————————————
(二)、反汇编时一般不能完全还原为原来的代码
eg:
JC again;在反汇编时会以JB出现
(三)、syntax error
语法错误,如宏命令与已有的指令名,标号名冲突
(四)、关于MOV的用法:
Mov dst, src
Reg reg/mem/data/segreg
Mem reg/data/segreg
Segreg reg/mem
Ac mem(ac指ax,al,该指令较其它指令短一个字节,执行速度也快些)
Mem ac
注:
1、SEGREG只能出现在MOV,PUSH,POP中
2、Mov mem,mem;错误,如MOV byte ptr [BX],[SI]; Illegal memory reference
3、MOV segreg,data;错误,立即数不能传给Segreg
4、MOV segreg,segreg ;SEGMENT不可相互传送
(五)、ASSUME作用(猜测):
ASSUME 作用:汇编时在符号表中记录下——变量和标号的段存储位置,如CS、DS、SS。
汇编程序遇到变量、标号时动作:
1、在对变量操作指令中,汇编程序会在符号表中查找该变量的段地址存放地点、偏移地址(段地址存放地点由ASSUME 指定如果没有ASSUME 指定,会报错Can't address with currently ASSUMEd segment registers)。
2、在对标号操作指令中,汇编程序会在符号表中查找该标号的段地址存放地点、偏移地址(段地址存放地点由ASSUME 指定, 如果没有ASSUME 指定,会报错Near jump or call to different CS)。
注意后最几段(39行后)的对变量NO(在CODE中定义)和BUF(在DATA中定义)的寻址,如果没有ASSUME,汇编时就会报错。
30 0009 C6 07 01 mov byte ptr [bx],1;use ds
31 000C C6 07 01 mov byte ptr ds:[bx],1;use ?
32 000F C6 47 01 01 mov byte ptr 1[bx],1;use ds
33 0013 C6 47 01 01 mov byte ptr ds:1[bx],1;use ?
34 0017 36: C6 07 01 mov byte ptr ss:[bx],1;use ?
35 001B C6 46 00 01 mov byte ptr [bp],1;use ss
36 001F 3E: C6 46 00 01 mov byte ptr ds:[bp],1;use ?
37 0024 3E: C7 46 00 0001 mov ds:[bp],1;use ?
*Warning* /y/a.ASM(28) Argument needs type override
38 002A 3E: C6 46 00 01 mov byte ptr ds:[bp],1;use ?
39 002F C6 87 0000r 01 mov buf[bx],1;use ds
40 0034 C6 87 0001r 01 mov buf+1[bx],1;use ds
41 0039 2E: C6 87 0005r 01 mov no[bx],1;use ?
42 003F 3E: C6 86 0000r 01 mov buf[bp],1;use ss
43 0045 2E: C6 86 0005r 01 mov no[bp],1;use ?
44 004B C6 06 0000r 01 mov buf,1
45 0050 2E: C6 06 0005r 01 mov no,1
注:1、使用默认段比使用段跳转速度快一些,因为段跳转会在操作码前增加一个字节
2、使用间接寻址比使用相对寻址要快,因为相对寻址还要经相加得到地址(如NO[BX]),而且其指令较长
EG:mov byte ptr [bx],1(3字节)比mov byte ptr[bp],1(四字节)短一个字节
30 0009 C6 07 01 mov byte ptr [bx],1;use ds
35 001B C6 46 00 01 mov byte ptr [bp],1;use ss
因为mov byte ptr[bp],1在汇编时被认为是MOV TYTE PTR[BP+00],1,即相对寻址方式,而不是间接寻址方式
(六)、输入时单十进制数据是以实际数值ASCII码保存的(高于实际值30H),如果只是用于加减运算、被除、被乘运算,为了方便显示,可以不必再去减30H。
如:输入7个数(0~9),求其平均值,得到的平均值整数部分的ASCII码(高于实际值30H),所以其整数部分可以直接显示,而只有余数是实际数值
(七)、关于类型指示PTR的使用:
双操作数,如双方类型不明确,就应当使用PTR,否则程序就默认为WORD型。.
36 001F 3E: C6 46 00 01 mov byte ptr ds:[bp],1;BYTE
37 0024 3E: C7 46 00 0001 mov ds:[bp],1;WORD
*Warning* /y/a.ASM(28) Argument needs type override,
注:如下双内存操作数,都是不合法的:
MOV [BX],[SI];error:Illegal memory reference非法内存参数
MOV byte ptr [BX],[SI];error:Illegal memory reference非法内存参数
MOV byte ptr [BX], byte ptr [SI];error:Illegal memory reference非法内存参数
(八)、mov [2134],bx在很多汇编软件中会报错:Illegal immediate
该指令在实际编程中是不可能用到的(我们一般都是利用变量名来对内存进行寻址)
因为,汇编时内存的偏移与段基址都是浮动的(偏移地址(r)在连接时才被最终确定下来,段地址(s)在程序运行时才被最终确定下来)
注:如果指令MOV [2134],BX在连接时,有另外一个段要同连接到此指令所处的段相连接,那么偏移2134必须改变,否则程序运行仍然指向2134。如果使用变量名MOV NUM,BX,在连接时就能适应偏移改变的要求(因为汇编程序建立了NUM的符号表,连接时会根据符号表中NUM的位置信息来改变指令中NUM的偏移)。
(九)、标号伪指令
用于标号或者变量的命名:
Bufw label word(无=、equ)
BUFW EQU this word
Bufw = this word
--------上面的三条指令应该放在地址入口前面----
Bufw EQU word ptr bufb
Bufw =word ptr bufb
注:(ptr与this的作用是相同的)
(十)、解决8086中条件跳转不能用NEAR的麻烦:
Relative jump out of range by 0126h bytes
8086中的条件跳转只有short类型;80186的条件跳转增加了near类型。当使用了的条件跳转超出SHORT型的范围就会报此错。(参看《汇编语言程序设计》第117页,朱玉龙 任文岚 朱彤编著 清华大学出版社)
解决方法:
1、如果超过的字节数较少,可以优化代码,减少中间代码的字节数。
2、把部分中间代码移到其它位置定义成函数。
3、把条件跳转改成jmp指令和一条相反的条件跳转指令。例如:
Ll:
; ……
jz Ll
改成:
L1:
; ……
jnz L2
jmp L1 ;jmp是非条件跳转,有SHORT,NEAR,FAR型
L2:
4、几乎所有的跳转指令都成对,所以上面的‘二级跳’做法总行得通。但是极少跳转指令(JCXZ和LOOP)没有相对应的指令,可以采用如下的‘三级跳’
Jcxz skip
Jmp short skip1(提前引用如果不使用SHORT,此跳转就被汇编为NEAR)
Skip:jmp lab
Skip1:
5、可以将3、4语句写成相应的宏指令***M,如JNZ写成能支持远调用的宏指令JNZM,其中在文件头可以加入JUMPS后就完全可以实现这样的宏功能
当在.asm文件头加入JUMPS时,生成的LIST文件为:
75 03 E9 FE57 je start1
L1:
可以看到:TASM自动对上面的指令作了跳转处理,这里的指令码:75 03 E9 FE57表示的是两个指令:75 03指的是jne L1的机器码;E9 FE57是jmp start1的机器码
6、可以在需要使用条件跳转的指令前加入.386,在指令后加入.8086:
0F 84 FE58 je start1
这个已经不是8086的指令了,而是386指令(是一条指令)
注:I、有部分汇编工具如(MASM FOR WINDOWS)带有上述5所述的功能,就不会出现超出跳转范围的错误。
II、上面的例子中,我对机器码的验证是通过DEBUG得出的.
在16BIT DEBUG下
-A
-****:**** DB 75 03 E9
-****:****
-U
在32位 DEBUG下