现在的位置: 首页 > 综合 > 正文

一个菜鸟作的一点汇编笔记

2013年08月15日 ⁄ 综合 ⁄ 共 4370字 ⁄ 字号 评论关闭

这学期学微机原理,顺便学了点汇编,遇到了很多问题,到百度上去求助几乎没人理我,到CSDN来后发现这里的大牛们特别热情,以后就在CSDN扎根了。

下面是我作的一点点笔记(有许多点子还是大牛们告诉我的),如果其中的错误的地方还希望大家指出。马上就得回家了,就不再排版了,以后再修改。

 

 我用的汇编工具是TASM,对于其它的工具可能结果不同 。

(一)、汇编缩写表:

DBDefine 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(acax,al,该指令较其它指令短一个字节,执行速度也快些)

Mem              ac

       :

1SEGREG只能出现在MOV,PUSH,POP

       2Mov mem,mem;错误,如MOV byte ptr [BX],[SI]; Illegal memory reference

3MOV segreg,data;错误,立即数不能传给Segreg

       4MOV segreg,segreg ;SEGMENT不可相互传送

 

(五)、ASSUME作用(猜测)

ASSUME 作用:汇编时在符号表中记录下——变量和标号的段存储位置,如CSDSSS

汇编程序遇到变量、标号时动作:

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],13字节)比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];errorIllegal memory reference非法内存参数

MOV byte ptr [BX],[SI];errorIllegal memory reference非法内存参数

MOV byte ptr [BX], byte ptr [SI];errorIllegal 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

注:(ptrthis的作用是相同的)

(十)、解决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、几乎所有的跳转指令都成对,所以上面的‘二级跳’做法总行得通。但是极少跳转指令(JCXZLOOP)没有相对应的指令,可以采用如下的‘三级跳’

       Jcxz skip

       Jmp short skip1(提前引用如果不使用SHORT,此跳转就被汇编为NEAR)

Skip:jmp lab

Skip1:

5、可以将34语句写成相应的宏指令***M,如JNZ写成能支持远调用的宏指令JNZM,其中在文件头可以加入JUMPS后就完全可以实现这样的宏功能

当在.asm文件头加入JUMPS,生成的LIST文件为:
75 03 E9 FE57     je start1

L1:
可以看到:TASM自动对上面的指令作了跳转处理,这里的指令码:75 03 E9 FE57表示的是两个指令:75 03指的是jne L1的机器码;E9 FE57jmp 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

抱歉!评论已关闭.