汇编语言数组中查找正数代码分析(3)

 

《Intel汇编语言程序设计》(第四版)第六章中的代码,如下:

 

.data

array SWORD -3 , -6 , -1 ,  -10 , 10 , 30 , 40 , 4

sentinel SWORD 0

.code

         mov esi , OFFSET array

         mov ecx , LENGTHOF array

        

next:

         test WORD PTR [esi] , 8000h          ; test sign bit

         pushfd                                            ; push flags on stack

         add esi , TYPE array

         popfd                                              ; pop flags from stack

         loopnz next                                    ; continue loop

         jnz quit                                           ; none found

         sub esi , TYPE array                        ; ESI points to value

quit:

 

 

让我们逐句分析。

 

程序在数据段定义了一个数组和一个变量:

 

.data

array SWORD -3 , -6 , -1 ,  -10 , 10 , 30 , 40 , 4

sentinel SWORD 0

 

然后,程序对 esi 和 ecx 进行赋值:

 

         mov esi , OFFSET array

         mov ecx , LENGTHOF array

 

将 esi 指向了数组array的第一个元素地址,并将array数组长度赋值给ecx。

 

接着,开始在数组中查找是否有正数,代码如下:

 

 

next:

         test WORD PTR [esi] , 8000h          ; 使用test伪指令对最高位进行“与”操作,如果为1则零标志ZF会被置1         pushfd                                            ; 保存标志位到堆栈(不明白这里为什么要保存标志位,但肯定是因为下面的操作会影响到标志位)

         add esi , TYPE array                        ; 将esi指向下一个数组元素地址

         popfd                                              ; 从堆栈中弹出标志位

         loopnz next                                    ; 在ECX中的无符号值大于0并且零标志位被清除的状态下进行循环

         jnz quit                                           ; 如果数组中未找到正数,则跳到quit标号处

         sub esi , TYPE array                        ; 如果找到了正数,则将esi减掉array元素类型即为正数地址

quit:

 

 

首先是几个伪指令的含义:

LOOPNZ指令的作用是,在ECX中的无符号值大于0并且零标志位被清除的状态下进行循环。

而TEST指令的作用是,只有当所有的测试位都被清除的时候,零标志位ZF才被置1。

JNZ指令的作用是,ZF=0时跳转。

 

 

整个程序的思路是这样的:

 

程序对每一个元素值的高位进行test测试,当是负数的时候,最高位是1,此时使用8000h(8000h 即 1000 000 000 000b)进行test的结果是测试位并不全为零,所以此时零标志位ZF被置为0,满足loopnz的两个条件,会继续执行。当最高位不是1的时候,则为正数,此时使用8000h进行test的结果是,所有测试位都被清除,则ZF会被置为1,因为不满足LOOPNZ的条件,所以不会接着执行循环,会跳出循环向下执行,因为也不满足下一条语句jnz的条件,所以不会跳转到quit标号。接着往下执行,因为之前 esi 被前移了一个元素,所以此时将 esi 减去一个元素,即得到刚刚检测到的正数的地址值。

 

所有程序完成。

你可能感兴趣的:(汇编语言)