• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

x86汇编_DIV / IDIV除法指令_笔记53

武飞扬头像
SilentHunter460
帮助1

无符号除法

32 位模式下,DIV(无符号除法)指令执行 8 位、16 位和 32 位无符号数除法,结果以余数和商的方式表现。格式如下:

DIV 8位寄存器或内存
DIV 16位寄存器或内存
DIV 32位寄存器或内存

被除数 除数 余数
AX reg/mem8 AL AH
DX:AX reg/mem16 AX DX
EDX:EAX reg/mem32 EAX EDX

根据以上表格可以总结出,div指令,当操作数是8位二进制,被除数就一定是16位,操作数是16位则被除数一定32位(两个16进制寄存器连起来)。也就是说被除数永远大于除数

下述指令执行 8 位无符号除法 (83h/2),生成的商为 41h,余数为 1:

  1.  
    mov ax, 0083h ; 被除数
  2.  
    mov bl, 2 ; 除数
  3.  
    div bl ; AL = 41h, AH = Olh

学新通

下述指令执行 16 位无符号除法 (8003h/100h),生成的商为 80h,余数为 3。DX 包含的是被除数的高位部分,因此在执行 DIV 指令之前,必须将其清零:

  1.  
    mov dx, 0 ; 清除被除数高16
  2.  
    mov ax, 8003h ; 被除数的低16
  3.  
    mov ex, 100h ; 除数
  4.  
    div ex ; AX = 0080h, DX = 0003h

学新通

下述指令执行 32 位无符号除法,其除数为内存操作数:

  1.  
    .data
  2.  
    dividend QWORD 0000000800300020h
  3.  
    divisor DWORD 00000100h
  4.  
    .code
  5.  
    mov edx, DWORD PTR dividend 4 ; 高双字
  6.  
    mov eax, DWORD PTR dividend ; 低双字
  7.  
    div divisor ; EAX = 08003000h, EDX = 00000020h

学新通

下面的 64 位除法生成的商 (0108 0000 0000 3330h) 在 RAX 中,余数 (0000 0000 0000 0020h) 在 RDX 中。请注意,由于被 64k 除,被除数中的每个十六进制数字是如何右移 4 位的。(若被 16 除,则每个数字只需右移一位。):

  1.  
    .data
  2.  
    dividend_hi QWORD 0000000000000108h
  3.  
    dividend_lo QWORD 0000000033300020h
  4.  
    divisor QWORD OOOOOOOOOOOlOOOOh
  5.  
    .code
  6.  
    mov rdx, dividend_hi
  7.  
    mov rax, dividend_lo
  8.  
    div divisor ; RAX = 0108000000003330
  9.  
    ; RDX = 0000000000000020

有符号数除法

有符号除法与无符号几乎相同,但是在计算前必须对被除数进行符号扩展

符号扩展指令
指令 全称 说明
cbw convert byte to word 将AL的符号位扩展到AH
cwd convert word to doubleword 将AX的符号位扩展到DX
cdq convert doubleword to quadword 将EAX的符号位扩展到EDX
  1.  
    .DATA
  2.  
    byte_val SBYTE -101
  3.  
     
  4.  
    .CODE
  5.  
    mov al, byte_val ; AL = 9Bh
  6.  
    cbw ; AX = FF9Bh
学新通
CBW指令,将AL的最高位值填充到AH,AH原来的内容被替换掉。

执行有符号除法前必须对被除数进行符号扩展,否则除法不会得到正确结果。具体先看以下例子:

  1.  
    .386
  2.  
    .model flat,stdcall
  3.  
    .stack 4096
  4.  
    ExitProcess proto,dwExitCode:dword
  5.  
    INCLUDE Irvine32.inc
  6.  
     
  7.  
    .data
  8.  
    wordval sword -101
  9.  
     
  10.  
    .code
  11.  
    main PROC
  12.  
    nop
  13.  
    mov dx, 0
  14.  
    mov ax, wordval
  15.  
    ;此时DX:AX=0000:FF9B,根据补码规则应当被解释为正65435。但我们需要的是-101
  16.  
    mov bx, 2
  17.  
    idiv bx ; 65435/2=327171
  18.  
    invoke ExitProcess,0
  19.  
    main ENDP
  20.  
     
  21.  
    end main
学新通

如果使用CBW指令:

  1.  
    .data
  2.  
    wordval sword -101
  3.  
     
  4.  
    .code
  5.  
    main PROC
  6.  
    nop
  7.  
    mov dx, 0
  8.  
    mov ax, wordval
  9.  
    cwd; DX:AX=FFFF:FF9B,这样的才能保证被除数是负101,否则会被解释为正65435
  10.  
    mov bx, 2
  11.  
    idiv bx
  12.  
    invoke ExitProcess,0
  13.  
    main ENDP

学新通

除法溢出

如果除法的商放不下容纳它的位置,就会产生除法溢出,这将导致处理器异常并暂停执行当前程序,以下指令产生了溢出,因为AL放不下十六进制数100h。

学新通

如果试图除以0,也会产生类似错误。

学新通

为了避免除数为0,可以用CPU跳转语句,发现除数是0就跳过div指令:

  1.  
    .code
  2.  
    main PROC
  3.  
    nop
  4.  
    mov ax, 20
  5.  
    mov bl, 0
  6.  
    cmp bl, 0
  7.  
    je NoDivideZero
  8.  
    div bl
  9.  
    nodividezero:
  10.  
    invoke ExitProcess,0
  11.  
    main ENDP

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhggeiea
系列文章
更多 icon
同类精品
更多 icon
继续加载