我必须编写一个程序,从输入文件中过滤文本行。每行被分为六列。列之间用分号分隔。
我实现了3个过滤器:
1.第二列不得包含u
或v
字母。
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
1条答案
按热度按时间waxmsbnn1#
在 * 过程属于间隔 * 中
A.
第6栏以新行结束,内容应为:
*B
DX应该是包含这些数字的缓冲区的地址,应该是:
C.
如果调度程序直接跳转到 .belongs,则SI将为1。
如果调度程序通过 .firstBound,则SI将为2或3。
如果调度程序通过 .secondBound,则SI将为2或3。
所有的数字都遵循模板X.XX,所以我建议这样写:
在 * 过程解析Int 16 * 中
目前你的程序并不解释这个proc返回的进位标志,但是如果它解释了,你会看到进位总是被设置的!
由于
clc
的编写位置,并且没有向此proc提交负数(即CL=0),因此cmp cl, 1
指令将设置进位。我的建议(
test
总是清除进位):