Home > other >  Implementing a function that checks if floating point number belongs to the given interval (YASM 808
Implementing a function that checks if floating point number belongs to the given interval (YASM 808

Time:12-21

I have to write a program that would filter text lines from the input file. Each line is divided into six columns. Columns are separated from each other by a semicolon.

I implemented 3 filters:

  1. Second column has to contain no u or v letters.
  2. Third column has to contain a number so that it's sum of digits is equal to 7.
  3. Last column has to contain number that belongs to the intervar of [2.34, 4.50]. Numbers are known to always be two decimals.

Here's input file example:

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

First two lines would pass all of three filters.

I implemented a function that checks if last column numbers belong to the given interval and if numbers do belong to the interval, the function should add them all together (considering that the line also passed two previous filters).

So with input example I am showing here, result should look like this:

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

However, my function that checks last column numbers seems to work incorrectly. What could be the problem?

EDIT: procBelongsToInterval function is updated

;[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 function:

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 function converts int16 value to string (ASCIIZ)

It does not add . between numbers. So the program prints 432 after calling the function if we use file example above.

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

CodePudding user response:

In procBelongsToInterval

A.

cmp al, ';'
je .setToZero

The 6th column ends with the newline. This should read:

cmp  al, 32
jb   .setToZero

B.

mov dx, [doubleNumbers]                 
call procParseInt16

DX is supposed to be the address of the buffer that contains the digits. This should read:

mov  dx, doubleNumbers                 
call procParseInt16

C.

mov  [doubleNumbers si], byte '$'       
mov  [bytesRead2], si               ; saving number of read bytes
  • You procParseInt16 uses 0 instead of $ as a terminator. Both codes have to agree.
  • SI does not always point behind the digits!
    If the dispatcher jumps straight to .belongs then SI will be 1.
    If the dispatcher passes through .firstBound then SI will be 2 or 3.
    If the dispatcher passes through .secondBound then SI will be 2 or 3.

All of the numbers follow the template X.XX, so I suggest writing:

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

In procParseInt16

clc
cmp cl, 1
je .negateAndReturn
jmp .return

Currently your program does not interpret the carry flag returned by this proc, but if it did you would see that the carry is always set!
Because of where you wrote clc and because you don't submit negative numbers to this proc (meaning CL=0), the cmp cl, 1 instruction will have set the carry.
My suggestion (test always clears the carry):

  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:
  • Related