2013-03-02 65 views
0

我刚开始学习assembly,我写了一些练习,但是我被卡在需要显示结果的部分。比较和打印EMU8086的值

描述:我有一个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)如何显示结果?

回答

2

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

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

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

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

第五个问题是您使用无符号条件跳转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 
+0

谢谢。我忘记了更新这个问题,但是我自己设法做到了:yestarday:D – Kosmog 2013-03-03 08:57:25