assembly 实现一个检查浮点数是否属于给定区间的函数(YASM 8086)

6xfqseft  于 2022-12-23  发布在  其他
关注(0)|答案(1)|浏览(101)

我必须编写一个程序,从输入文件中过滤文本行。每行被分为六列。列之间用分号分隔。
我实现了3个过滤器:
1.第二列不得包含uv字母。
1.第三列必须包含一个数字,使其位数之和等于7
1.最后一列必须包含属于[2.34, 4.50]区间的数字。已知数字总是两位小数。
下面是输入文件示例:

B11;one;16;0;55;2.44
C1;two;43;0;17;3.77
D2;three;47;0;15;5.41

前两条线将通过所有三个过滤器。
我实现了一个函数,它检查最后一列的数字是否属于给定的区间,如果数字确实属于该区间,该函数应该将它们加在一起(考虑到该行还通过了前面的两个过滤器)。
因此,对于我在这里展示的输入示例,结果应该如下所示:

B11;one;16;0;55;2.44
C1;two;43;0;17;3.77
6.21

然而,我的函数检查最后一列的数字似乎不正确的工作。什么可能的问题?
编辑:procBelongsToInterval函数已更新

;[2.34, 4.50]
procBelongsToInterval
    push ax
    xor ax, ax
    xor si, si

; saving floating point number digits to the buffer (without '.')
.read
    mov al, [di]
    inc di
    cmp al, '-'
    je .break
    cmp al, '.'
    je .read
    cmp  al, 32
    jb   .setToZero
    mov [doubleNumbers+si], al
    inc si
    jmp .read

; used si as a pointer to the next byte so have to set si to zero again
.setToZero
    xor si, si
    jmp .first

; checking if number is in the bounds [2.34, 4.50]
.first:
    mov al, [doubleNumbers+si]
    inc si
    cmp al, '2'
    je  .firstBound
    cmp al, '3'
    je  .belongs
    cmp al, '4'
    je  .secondBound
    jmp .break

.firstBound:
    mov al, [doubleNumbers+si]
    inc si
    cmp al, '3'
    jb  .break
    ja  .belongs
    mov al, [doubleNumbers+si]
    inc si
    cmp al, '4'
    jae .belongs
    jb  .break

.secondBound:
    mov al, [doubleNumbers+si]
    inc si
    cmp al, '5'
    ja  .break
    jb  .belongs
    mov al, [doubleNumbers+si]
    inc si
    cmp al, '0'
    je  .belongs
    ja  .break

; number belongs to the interval
.belongs:
    mov [numberBelongsToInterval], byte 1   ; boolean value
    mov  si, 3
    mov  [doubleNumbers+si], byte 0
    mov  [bytesRead2], si                   ; saving number of read bytes
    mov  dx, doubleNumbers                 
    call procParseInt16                     ; Extracts an integer of type int16 from the buffer whose address is DX. 
                                            ; Function saves result into AX register
    add [suma], ax                          ; Adding sum with value in AX
    jmp .end

.break:
    mov [numberBelongsToInterval], byte 0
    jmp .end

.end:
    pop ax
    ret

procParseInt16函数:

procParseInt16:
push dx
   push cx
   push si
   push di
   mov bx, dx
   mov ax, 0
   mov si, 0              ; number of digits 
   mov cl, 0              ; 0 - if nonnegative, 1 - otherwise
   ; eating spaces:
   .leading_spaces:
      cmp [bx], byte ' '
      jne .next1    
      inc bx
      jmp .leading_spaces
    
   .next1:
      cmp [bx], byte 0          ; the end of the string?
      jne .next2
      jmp .endParsing
   .next2:
      cmp [bx], byte '-'   ; the minus
      jne .digits
      mov cl, 1            ; negative number
      inc bx
   
   .digits:
      cmp [bx], byte '0'          
      jb  .lessThanNumeric
      cmp [bx], byte '9'          
      jbe  .updateAX
      .lessThanNumeric: 
         jmp .endParsing
      .updateAX:
         mov dx, 10
         mul dx
         mov dh, 0 
         mov dl, [bx]
         sub dl, '0'
         add ax, dx
         inc si
      inc bx 
      jmp .digits
   .endParsing:
      cmp si, 0                   ; empty string?
      je .setErrorAndReturn
      clc
      cmp cl, 1
      je .negateAndReturn
      jmp .return
   
   .negateAndReturn:
      neg ax
      jmp .return
          
   .setErrorAndReturn:
      stc

   .return:        
   pop di
   pop si
   pop cx
   pop dx
   ret

procInt16ToStr函数将int16值转换为字符串(ASCIIZ)
它不会在数字之间添加.。因此,如果我们使用上面的文件示例,则程序在调用函数后打印432

procInt16ToStr:
; Converts value from AX to ASCIIZ (decimal system)
; AX - int16 value
; DX - adress, where the result is placed
   push di    
   push si
   push cx
   push bx
   push dx
   mov bx, dx
   mov cx, 0     
   mov si, 0         
   cmp ax, word 0
   jge .next
     mov cl, 1
     mov [bx], byte '-'
     inc bx
     neg ax

  
  .next:
     mov dx, 0
     mov di, 10
     div di
     add dl, '0'
     mov [bx], dl
     inc bx
     inc si
     cmp ax, 0
     je .setSign
     jmp .next
    
  .setSign:
     

  .reverse:
  ;   inc bx
     mov [bx], byte 0             ; asciiz
     dec bx

     pop dx
     push dx
     mov di, dx 
    
     cmp cl, 1
     jne .Ok
     inc di
     
     .Ok:
     mov ax, si
     shr ax, 1
     mov cx, ax
     cmp cx, 0
     je .return
     
     .loopByDigits:
        mov al, [di]
        mov ah, [bx]
        mov [di], ah
        mov [bx], al
        dec bx
        inc di
        loop .loopByDigits

  .return: 
  pop dx
  pop bx
  pop cx
  pop si
  pop di
  ret
waxmsbnn

waxmsbnn1#

在 * 过程属于间隔 * 中

A.

cmp al, ';'
je .setToZero

第6栏以新行结束,内容应为:

cmp  al, 32
jb   .setToZero

*B

mov dx, [doubleNumbers]                 
call procParseInt16

DX应该是包含这些数字的缓冲区的地址,应该是:

mov  dx, doubleNumbers                 
call procParseInt16

C.

mov  [doubleNumbers+si], byte '$'       
mov  [bytesRead2], si               ; saving number of read bytes
    • procParseInt 16 * 使用0而不是$作为终止符。两个代码必须一致。
  • SI并不总是指向数字后面!

如果调度程序直接跳转到 .belongs,则SI将为1
如果调度程序通过 .firstBound,则SI将为23
如果调度程序通过 .secondBound,则SI将为23
所有的数字都遵循模板X.XX,所以我建议这样写:

mov  si, 3
mov  [doubleNumbers+si], byte 0
mov  [bytesRead2], si               ; saving number of read bytes

在 * 过程解析Int 16 * 中

clc
cmp cl, 1
je .negateAndReturn
jmp .return

目前你的程序并不解释这个proc返回的进位标志,但是如果它解释了,你会看到进位总是被设置的!
由于clc的编写位置,并且没有向此proc提交负数(即CL=0),因此cmp cl, 1指令将设置进位。
我的建议(test总是清除进位):

test si, si        ; empty string?
  stc
  jz   .return       ; Yes, CF=1
  test cl, cl        ; positive number?
  jz   .return       ; Yes, CF=0
  neg  ax
  clc
.return:

相关问题