9-常用的汇编指令

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35733751/article/details/85055530

1. 逻辑运算指令

在汇编语言中逻辑运算指令有:与运算指令,或运算指令,非运算指令,异或运算指令。分别用and、or、not、xor来表示。

以and指令举例:

mov ax,0xFFFF       ;ax=1111 1111 1111 1111
mov bx,0xF0F0	    ;bx=1111 0000 1111 0000
and ax,bx           ;ax和bx进行与运算,将结果赋值给ax


上面三条指令相当于:
      1111 1111 1111 1111
and   1111 0000 1111 0000
___________________________
      1111 0000 1111 0000

ax的结果转换为十六进制0xF0F0。

 

 

以xor指令为例:

mov ax,0x1234    ;ax=0001 0010 0011 0100
xor ax,ax        ;将ax与自己做异或运算,将结果赋值给ax


上面的指令相当于:
        0001 0010 0011 0100
xor     0001 0010 0011 0100  
_______________________________ 
        0000 0000 0000 0000

ax的结果为0x0000

 

or指令和not指令都是类似的......

 

2. 算术运算指令

我们知道add指令是用于加法运算的,而sub指令则正好相反,它是用于做减法运算的。

 

dec指令是用于自减一的

mov ax 0x001
dec ax         ;执行完这条指令后,寄存器ax的内容就会减一

inc指令同dec指令相反,是用于自增一的,也就是说,执行完inc指令后,对应的寄存器里的内容就会+1。

3. 用于重复执行的指令——loop

loop指令可以把一段代码重复执行多次。

执行loop指令的时候会做两件事:

  1. 将寄存器CX的内容减一
  2. 如果CX的内容不为0,转移到指定的位置处执行,如果cx中的值为0则向下执行其他的指令

 

汇编代码如下:

	                        ;文件名004.asm
	                        ;说明:loop指令示例


mov ax,0x00	;ax的初值为0
mov cx,0x5	;寄存器cx里存放的就是循环次数

mark:
;inc指令会让寄存器ax的内容每次自增1,这一段就是我们要重复执行的代码,即循环体
inc ax

;判断cx , 如果不为0那么跳转到循环体继续执行
loop mark	

;如果cx为0,则往下顺序执行其他指令

times 510-($-$$) db 0x00
db 0x55,0xAA  

执行结果:

我们可以看到寄存器AX的内容以及自增到5了,当寄存器cx的值为0后就不再跳转到循环体执行了,而是往下顺序执行其他指令。

另外,loop指令每次跳转的时候都会修改IP寄存器里的值,大家在调试的时候注意观察,当执行loop,-3指令时就会跳转到0x7c06的位置执行循环体,那到底是怎么跳转的呢?

首先我们知道loop,-3指令占用2字节,并且它的起始地址为0x7c07,当执行完这条指令后,IP寄存器就会变成0x7c09,然后0x7c09减3就可以得出相对位置0x7c06了,因为这里cs地址为0,所以把cs和ip组合计算出物理地址就是0x7c06。当然,这个相对地址实际上是由编译器计算出来的。

4. 用loop指令优化代码

之前学习了一个loop指令,loop指令是目前为止比较复杂的一个指令,说它复杂是相对jmp、mov、add、inc、dec这样的指令来说。loop指令在执行时会把cx减1,检测cx是否为0,决定接下来是否要修改IP寄存器的值来实现跳转

计算机本来就非常擅长做一些重复性高的事情,有时候我们在编写程序时为了完成某一件事情会出现很多重复性的代码,例如第7篇我们写的第一个汇编程序,其中有些代码是完全可以优化的,而接下来我们要学习如何使用loop指令进行优化代码。

在此之前,我们需要用到两个新的寄存器:si  (Source Index)和di  (Destination Index) 。si寄存器表示源地址的意思,di表示目的地址的意思。

汇编代码如下:


		                ;文件名:005.asm
		                ;说明:loop指令优化


;指定显存段
mov ax,0xB800
mov es,ax

;指定数据段
mov ax,0x07C0
mov ds,ax

mov cx,code-string	;指定循环次数
mov si,0            ;初始化数据段 偏移寄存器
mov di,0            ;初始化显示段 偏移寄存器

jmp 0x07C0:code

string: 
db 'hello world'

;因为我们最终是要把数据段里的数据存到显存段里
;所以在si源地址指定为数据段,di目的地址指定为显存段
;而下面这段代码就是从数据段中循环取出数据放到显存段里
code:
mov al,[ds:string+si]  
mov byte [es:di],al
inc di
mov byte [es:di],0x07	;白底黑字
inc si
inc di
loop code		;继续循环

end:
jmp 0x07C0:end

 times 510-($-$$) db 0x00
db 0x55,0xAA

执行结果如下:

猜你喜欢

转载自blog.csdn.net/qq_35733751/article/details/85055530
今日推荐