在汇编语言中test ax 01h是什么意思,到底是哪些位进行相与了?

如题所述

    1

    程序如下(R4R5R6R7/R2R3=R6R7):

    ;This program for:R4R5R6R7/R2R3=R6R7 ;Remainder=(R4R5)

    ;----------------------------------------------------------------

    ;define stack segment

    STACK           SEGMENT STACK 'STACK'

    DB 1024 DUP (0)

    STACK           ENDS

    ;define data segment

    DATA            SEGMENT

    BWORD   EQU     THIS    BYTE           

    R0      DW      (?)

    R1      DW      (?)

    R2      DW      (?)

    R3      DW      (?)

    R4      DW      (?)

    R5      DW      (?)

    R6      DW      (?)

    R7      DW      (?)

    DATA            ENDS

    ;define code segment

    NBDIV           SEGMENT

    ;

    MAIN            PROC FAR

    ASSUME  CS:NBDIV,DS:DATA,SS:STACK

    ;

    START:          PUSH    DS        ;return DOS standard program

    MOV     AX,0

    PUSH    AX

    MOV     AX,DATA   ;set DS

    MOV     DS,AX

    MOV     AX,R5

    SUB     AX,R3

    MOV     AX,R4

    SBB     AX,R2

    JNC     DIV4    ;Over process

    MOV     CX,32                 ;

    DIV1:           CLC

    RCL     R7,1

    RCL     R6,1

    RCL     R5,1

    RCL     R4,1

    PUSHF

    POP     R0      ;Store RF to R0

    MOV     AX,R5

    SUB     AX,R3

    MOV     R1,AX

    MOV     AX,R4

    SBB     AX,R2

    PUSHF

    TEST    BYTE PTR R0,01H

    JNZ     DIV21

    POPF

    JNC     DIV2

    JMP     DIV3

    DIV21:          POPF

    DIV2:           MOV     R4,AX

    MOV     AX,R1

    MOV     R5,AX

    INC     R7

    DIV3:           LOOP    DIV1

    STC

    DIV4:           RET

    MAIN            ENDP

    NBDIV           ENDS

    END     START

    上一篇我们说过了,这是把图中过程用汇编语言实现的程序

    而且还顾及到了下面的问题

    1、判断够减或不够减的方法

    2、够减时的处理方法

    3、不够减时的处理方法

    4、商上1的位置和方法

    5、商上零的方法

    2

    STACK           SEGMENT STACK 'STACK'

    DB 1024 DUP (0)

    STACK           ENDS

    ;define data segment

    DATA            SEGMENT

    BWORD   EQU     THIS    BYTE             

    R0      DW      (?)

    R1      DW      (?)

    R2      DW      (?)

    R3      DW      (?)

    R4      DW      (?)

    R5      DW      (?)

    R6      DW      (?)

    R7      DW      (?)

    DATA            ENDS

    ;define code segment

    NBDIV           SEGMENT

    ;

    MAIN            PROC FAR

    ASSUME  CS:NBDIV,DS:DATA,SS:STACK

    ;

    START:          PUSH    DS        ;return DOS standard program

    MOV     AX,0

    PUSH    AX

    MOV     AX,DATA   ;set DS

    MOV     DS,AX

    这一部分是程序的一些定义,初始化的代码,比较简单,但需要一些微机的知识,我们这里不讲解这一部分,而是主要讲解功能实现的部分

    3

    其中讲解一下几个命令

    PUSHF  POPF,一个是入栈,一个是出栈,但与PUSH,POP不同的是,PUSHF入栈的内容是确定的,就是标志寄存器的所有的标记位,也就不单单是cf或者af之类,而是所有,POPF也是一样,内容出栈,但出栈的内容去哪里是确定的,就是覆盖标志寄存器的内容

    JNC, JNC是单单判断标记寄存器中的CF位是不是0,如果是0,就跳转,不是就不跳转。

    JNZ 也是差不多,不过它是判断上一条指令的结果是不是零,如果不是0,就跳转,是0就不跳转,这里就与JNC刚好相反,当然也可以这么说,JNZ判断标记寄存器中的ZF位是不是0,如果上一条指令的结果不是零,则ZF就为0,如果ZF为0,则跳转。两种说法是一样的。

    JMP,是无条件跳转,也就是,前面无论发生什么都与它无关,它只负责跳转

    RCL ,是向左移一位,把低位补上标记寄存器CF的值,并把高位存储覆盖标记寄存器CF的值

    CLC,是把标记寄存器中的CF位 置零

    STC,是把标记寄存器中的CF位 置一

    其他命令都比较好理解就不说了

    4

    MOV     DS,AX

    MOV     AX,R5

    SUB     AX,R3

    MOV     AX,R4

    SBB     AX,R2

    JNC     DIV4    ;Over process

    MOV     CX,32                 ;

    这里讲一下这一行内容,这是初始化紧接着的内容,这段内容的意义主要是解决判断算式是否是可执行的,我们知道程序的式子是:R4R5R6R7/R2R3=R6R7

    上面几行代码的意思就是判断R4R5是不是比R2R3大,如果是就跳到DIV4,但为什么要这么做?别急,请看下面

    5

    (一)篇的式子商是1100,我们修改一下式子,如下图所示,结果变成了

    10011,1100是四位二进制,但10011时五位二进制,原因是被除数11000001

    的前四位1100比除数1010大

    我们回到程序,为什么R4R5不能比R2R3大,因为如果R4R5比R2R3大,得到的结果就比R6R7的位数大,一个字节是8位,一个字是两个字节,R0~R7是字,即16位二进制,R6R7是双字,共32位二进制,我们设定商是R6R7,即商只能是32位二进制,如果R4R5比R2R3大,则商多于32位,则无法显示正确结果。当然,如果你设置结果是R0R1R6R7,即和被除数一样是64位,是允许R4R5比R2R3大的。不过这就需要改动一些代码这里就不讨论了

    6

    CLC

    RCL     R7,1

    RCL     R6,1

    RCL     R5,1

    RCL     R4,1

    就是把被除数整体左移一位,并把末尾一位补上零,把最高位存储在CF标记寄存器

    如果被除数是

    ffff ffff ffff ffff ffff ffff ffff ffff 

    执行上面代码后变成

    ffff ffff ffff ffff ffff ffff ffff fffe 

    CF的值就为1

    7

    PUSHF

    POP     R0      ;Store RF to R0

    这行的意思就是把寄存器的内容存储在R0上,作用等下再说

    8

    MOV     AX,R5

    SUB     AX,R3

    MOV     R1,AX

    MOV     AX,R4

    SBB     AX,R2

    以上的代码很好理解,但意义是什么呢?

    这个程序中的式子是R4R5R6R7/R2R3=R6R7,在(一)篇中,我们设置商是Q,余数是R,但在程序 R6R7是商(Q),R4R5是余数(R),除数是R2R3(B),所以我们可以套用(一)篇的内容来解释,用R4R5作为余数事实上,就是先左移32位进R,但上面我们已经说过了,一开始R4R5是不能比R2R3大的,所以这里代码就继续左移一位,这样再比较余数R是不是比被除数B大,是,商就左移进一个1并使余数等于R-B的差,即执行如下代码,下面的代码就是把差存进R中,并把R7最后一位变为1

    DIV2:        MOV     R4,AX

    MOV     AX,R1

    MOV     R5,AX

    INC     R7

    但如果余数R4R5并不是比R2R3大,商就左移进一个0。

    这里需要解释一为什么用 INC     R7,INC     R7是给R7加1的意思,为什么要加1呢,首先我们在前面的时候执行了下面代码

    CLC

    RCL     R7,1

    RCL     R6,1

    RCL     R5,1

    RCL     R4,1

    首先我们要知道R6R7既是被除数一部分,又是商,我们在左移被除数时,已经默认左移了一个0进商R6R7最后一位去了,所以我们只要加1把这个零改成1就行了,如果余数R4R5不是比R2R3大,也不需要左移一个0了,因为已经移了。这里需要理解(一)篇的内容才行。                

    9

    PUSHF

    TEST    BYTE PTR R0,01H

    JNZ     DIV21

    POPF

    上面代码是什么意思,首先BYTE PTR R0是指定R0低位的字节,TEST是把R0低位的字节与01H进行与运算。那么意义是什么呢,首先看前面的两行代码

    PUSHF

    POP     R0      ;Store RF to R0

    可以知道R0现在存储是之前左移后的标记寄存器的内容。

    这里我们还是回到(一)篇的内容,

    我们假设一个方程

    A/B=Q,余数是R

    其中(二进制)

    A=10000001

    B=1010

    从(一)篇可以知道,有10000-1010这一步,这里商应该被左移进一个1,但是在程序中虽然10000是比1010大的,但程序只比较和除数一样位数的值,即在程序中比较的0000与1010的大小,进行的是0000-1010的借位减法,所以CF

    是1,这样 JNC     DIV2,这一步就不会跳转到DIV2,商就不会被左移进一个1,造成结果的错误,所以,我们这里保证如果执行

    CLC

    RCL     R7,1

    RCL     R6,1

    RCL     R5,1

    RCL     R4,1

    后,CF的值变成1,即被除数原最高位是1这种情况下,商应该被左移进一个1,因为这种情况下,不应该是0000-1010,而是10000-1010,必定是商应该被左移进一个1的。

    DIV21:          POPF

    这里是为了进行两次POPF,使CF变成0

    这样 JNC     DIV2,这一步就可以跳转到DIV2

    10

    这样程序就基本讲解完成了,比较难理解的是步骤9,其实简单来说就是R4R5可能比R2R3小,但如果进位的CF是1,CF R4R5就一定比R2R3大,就是这么一个道理。

温馨提示:答案为网友推荐,仅供参考
相似回答