在EMU8086中比较和打印值

时间:2013-03-02 16:50:21

标签: assembly x86 x86-16

我刚开始学习assembly并且我写了一些练习线,但我被困在需要显示结果的部分。

说明:我有min值和max值。我将这些值与array进行比较,尝试仅显示不在inteval([min,max]

中的值

以下是我的尝试(我知道我对此非常不好,抱歉!):

include emu8086.inc

ORG 100h   

mov cx, 5    

verificareMinim:   
           MOV AX,date                                                                                  
           MOV BX,minInterval                                                                                 
           CMP AX,BX 
           JB belowMinResults   

 loop verificareMinim      ; sfarsit pasul 1 



 verificareMaxim:  
            MOV AX,date 
            MOV BX,maxInterval
            CMP AX,BX
            JA  overMaxResults

  loop verificareMaxim  ; sfarsit pasul 2


 belowMinResults:
            int 21h
            JMP verificareMinim

 overMaxResults:  
            int 21h
            JMP verificareMaxim



maxInterval DW 10
minInterval DW 1
date DW -1,-4,11,3,7

RET ; return to operating system.
END ; directive to stop the compiler.

所以,我的问题是:

1)我的代码有什么问题? (问题如上所述,Description

2)如何显示结果?

1 个答案:

答案 0 :(得分:2)

如果只想打印适合范围的数组,则不需要使用2个循环使其过于复杂。一个循环就足够了。

另一个问题是您没有为int 21h DOS调用设置任何有意义的参数。

第三个问题是你没有更新你的指针。

第四个问题是您在第一个(cx)循环后没有再次设置verificareMinim

第五个问题是您对签名号码使用无符号条件跳转jbja

第六个问题是你的代码进入无限循环,因为当loop verificareMaxim不再分支到verificareMaxim时,执行继续belowMinResults然后(如果int 21h不会崩溃,也就是说,JMP verificareMinim使它成为一个无限循环。

第七个问题是ret指令在您的数据之后,并且永远不会到达。

你可以这样做:

    mov si,date ; si points to the array.
                ; some assemblers want mov si,offset array.
                ; lea si,date may also be used.

    mov cx,5    ; length of array date

修改:打印间隔中的数字。固定的。

修改:修正了十六进制打印中的错误。

@verify_loop:
    mov ax,[si]           ; read value from array into ax
    cmp ax,[minInterval]  ; compare value of ax with the value of min_Interval
                          ; some assemblers want cmp ax,min_Interval
    jl  @number_is_ok     ; jump if less, signed conditional jump.

    cmp ax,[maxInterval]  ; compare value of ax with the value of max_Interval
                          ; some assemblers want cmp ax,max_Interval
    jle @number_not_valid ; jump if less or equal, signed conditional jump.

@number_is_ok:

    ; the number in ax is valid, print it here.

    ; I'll do the printing here the easy way: printing in
    ; hexadecimal, printing in other formats (say, decimal) left as an exercise.
    ; hint: use div and print always the remainder after converting it to ASCII
    ; 0...9.
    ;
    ; I'll just use int 21h/ah=02h here, dl contains the character to write.

    push cx

    mov cl,12d ; number of bits to shift.
               ; start with 12 (it's 16 minus 4).

    @print_loop:
        mov dx,ax

        shr dx,cl   ; shift dx cl bits to the right
        and dl,0x0F ; leave only the lower nibble (4 bits)
        cmp dl,9
        jbe @between_0_and_9 ; jump if between or equal to 9
                             ; (unsigned conditional jump)

            add dl,('a'-'9'-1) ; Edit: fixed bug here.
                               ; Lowercase hexadecimal letters a-f
                               ; (change to 'A' for uppercase)
    @between_0_and_9:
        add dl,'0'           ; convert to printable ASCII '0'...'9', 'a' ... 'f'

        push ax    ; according to Ralph Brown's interrupt list,
                   ; int 21h/ah=02 modifies al.
        mov ah,2   ; print character to screen
        int 21h    ; character in dl
        pop ax

        sub cl,4        ; next time shift 4 bits less
        jnc @print_loop ; continue if there's still bits left

    pop cx

@number_not_valid:
    add si,2            ; next word in array date.
    dec cx              ; decrement counter.
    jnz @verify_loop    ; continue if there's still words in array date.

; now everything is done.

    mov ax,4C00h
    int 21h      ; int 21h/ah=4Ch, return to DOS, return code in al.
                 ; int 20h works too, no return code.
                 ; ret works too, but only in .COM files.

maxInterval DW 10
minInterval DW 1
date        DW -1, -4, 11, 3, 7