• 汇编语言IDICV指令:有符号数除法

    有符号除法几乎与无符号除法相同,只有一个重要的区别:在执行除法之前,必须对被除数进行符号扩展。

    符号扩展是指将一个数的最高位复制到包含该数的变量或寄存器的所有高位中。为了说明为何有此必要,让我们先不这么做。下面的代码使用 MOV 把 -101 赋给 AX,即 DX:AX 的低半部分:

    .data
    wordVal SWORD -101      ; 009Bh
    .code
    mov dx, 0
    mov ax, wordVal         ; DX:AX = 0000009Bh (+155
    mov bx, 2               ; BX 是除数
    idiv bx                 ; DX:AX除以BX (有符号操作)

    可惜的是,DX:AX 中的 009Bh 并不等于 -101,它等于 +155。因此,除法产生的商为 +77,这不是所期望的结果。而解决该问题的正确方法是使用 CWD( 字转双字 ) 指令,在进行除法之前在 DX:AX 中对 AX 进行符号扩展:

    .data
    wordVal SWORD -101      ; 009Bh
    .code
    mov dx, 0
    mov ax, wordVal          ; DX:AX = 0000009Bh (+155)
    cwd                      ; DX:AX = FFFFFF9Bh (-101 )
    mov bx, 2
    idiv bx

    x86 指令集有几种符号扩展指令。首先了解这些指令,然后再将其应用到有符号除法指令 IDIV 中。

    符号扩展指令(CBW、CWD、CDQ)

    Intel 提供了三种符号扩展指令:CBW、CWD 和 CDQ。CBW(字节转字)指令将 AL 的符号位扩展到 AH,保留了数据的符号。如下例所示,9Bh(AL 中)和 FF9Bh (AX 中)都等于十进制的 -101:

    .data
    byteVal SBYTE -101     ; 9Bh
    .code
    mov al, byteVal        ; AL = 9Bh
    cbw                    ; AX = FF9Bh

    CWD(字转双字)指令将 AX 的符号位扩展到 DX:

    .data
    wordVal SWORD -101     ; FF9Bh
    .code
    mov ax, wordVal         ; AX = FF9Bh
    cwd                     ; DX:AX = FFFFFF9Bh

    CDQ(双字转四字)指令将 EAX 的符号位扩展到 EDX:

    .data
    dwordVal SDWORD -101    ; FFFFFF9Bh
    .code
    mov eax, dwordVal
    Cdq                     ; EDX:EAX = FFFFFFFFFFFFFF9Bh

    IDIV 指令

    IDIV(有符号除法)指令执行有符号整数除法,其操作数与 DIV 指令相同。执行 8 位除法之前,被除数(AX)必须完成符号扩展。余数的符号总是与被除数相同。

    【示例 1】下述指令实现 -48 除以 5。IDIV 执行后,AL 中的商为 -9,AH 中的余数为 -3:

    .data
    byteVal SBYTE -48       ;D0 十六进制
    .code
    mov al, byteVal         ;被除数的低字节
    cbw                     ;AL扩展到AH
    mov bl,+5               ;除数
    idiv bl                 ;AL = -9, AH = -3

    下图展示了 AL 是如何通过 CBW 指令符号扩展为 AX 的:

更多...

加载中...