assembly SIGFP -但不能除以0或大数|多系统管理/用户管理

zpf6vheq  于 2023-01-13  发布在  其他
关注(0)|答案(1)|浏览(142)

执行除以10,我得到了一个"浮点异常"。当在GDB中单步执行代码时,我发现除除时ax = 23,bx = 10。

.686                                    ;
                                        ;
BSS SEGMENT                             ;
    BUF DB 0                            ;
BSS ENDS                                ;
                                        ;
DATA SEGMENT                            ;
    ASSUME DS:BSS                       ;
                                        ;
PUBLIC _start                           ;
_start PROC                             ;
    MOV cx, 230                         ;
    CALL prN                            ;
                                        ;
...
_start ENDP                             ;
                                        ;
;---------------------------------------;
; prNum                                 ;
; TOFIX: numbers are printed backwards  ;
;---------------------------------------;
; CX = number to print                  ;
;---------------------------------------;
prN PROC                                ;
    MOV ax, cx                          ; prepare first loop
    MOV bx, 10                          ; !! BX = 10
@@loop:                                 ;
    ;- PROBLEMATIC LINE vvvvvvvvvvvvvvvv;
    DIV bx                              ; Get rightmost decimal digit
    ;- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^;
    ADD dl, '0'                         ; convert to ASCII-numeral
    MOV BYTE PTR [BUF], dl              ;
    PUSHA                               ; Not ideal, this is a playground
    ;- print byte buffer                ;
...
    ;--                                 ;
    POPA                                ;
    OR ax, ax                           ; Is cx = 0?
    JNZ @@loop                          ; NO: loop for the next decimal part
    RET                                 ; YES: leave loop
prN ENDP                                ;
DATA ENDS
END

循环的示例(如我所想象的):

MOV ax, cx ; ax = 230
MOV bx, 10 ; bx = 10
           ;
(@@loop)   ;
DIX bx     ; ax = 23 - dx = 0
;- print   ; STDOUT = 0
OR ax, ax  ; ZF = 0
JNZ @@loop ; continue looping with AX = 23

DIV bx     ; AX = 2 - DX = 3 --> THIS is where the SIGFPE occurs
;- print   ; STDOUT = 03
OR ax, ax  ; ZF = 0
JNZ @@loop ; continue looping with AX = 2
           ;
DIX bx     ; AX = 0 - DX = 2
;- print   ; STOUD = 032 (230 but backwards)
OR ax, ax  ; ZF = 1
JNZ @@loop ; not looping
RET        ; all done, we are returning

由于我是用23除以10,所以我希望这个运算不会有问题,特别是:

  • 不被零除
  • 无溢流
  • 无下溢

我希望

AX = 2
DX = 3
BX = 10
ggazkfy8

ggazkfy81#

我疏忽了。16位DIV操作接收DX:AX。
由于DX在第一遍中为0x0030,所以我所除的数似乎不再有效:

DX = 0x0030 (48 in decimal)
AX = 0x0017 (23 in decimal)

0x00300017除以10大于0xFFFF。

if(Source == 0) Exception(DE); //divide error

if(OperandSize == 8) { //word/byte operation
  Temporary = AX / Source;
  if(Temporary > 0xFF) Exception(DE); //divide error
  else {
      AL = Temporary;
      AH = AX % Source;
  }
}
else if(OperandSize == 16) { //doubleword/word operation
  Temporary = DX:AX / Source;
  if(Temporary > 0xFFFF) Exception(DE); //divide error
  else {
      AX = Temporary;
      DX = DX:AX % Source;
  }
}
else { //quadword/doubleword operation
  Temporary = EDX:EAX / Source;
  if(Temporary > 0xFFFFFFFF) Exception(DE); //divide error
  else {
      EAX = Temporary;
      EDX = EDX:EAX % Source;
  }
}

https://c9x.me/x86/html/file_module_x86_id_72.html

相关问题