2012-04-02 11 views
5

私はNASM 16ビットを使用しています。私は各番号の間に1秒間隔で0から255までの数字を印刷する簡単なアセンブリコードを実行しようとしています。スクリーンに数字を表示してDOS x86アセンブリで1秒間スリープする方法はありますか?

[bits 16] 

mov ax,cs 
mov ds,ax 
mov cx,255 
mov ax,0 

myloop: 
    ;print in screen ax value 
    ;wait 1 second 
    inc ax 

loop myloop 

私は画面に斧の値を印刷する方法、および(コード内のコメントにそれらを置いた)1秒を待つためにかどうかはわかりません:これは私がこれまで持っているものです。

+0

これはパソコンでやっていますか? –

+0

@PavanManjunathはい、私はPCでそれをやっています。 Windows 7,32ビット。 –

+0

遅延部分については、[this](http://www.physicsforums.com/showthread.php?t=150424)スレッドの最後の投稿をチェックアウトすることができます。クロックは100MHzとする。しかし、試行錯誤して、マシンの正確な価値を把握する必要があります。 [This](http://www.programmersheaven.com/mb/x86_asm/272272/272273/re-sleep-function-/?S=B10000)リンクも遅延を正しく取得するのに役立ちます –

答えて

6

PC BIOSによって維持および更新されるセグメント0のオフセット46Ch(または代替的にseg 40h、offs 6Ch)の4バイトカウンタがあります。それは毎秒18.2回増分されます。このカウンタの最下位バイトまたはワードで18の変化おそらく約二を待っているの最も簡単な方法ですカウント:

mov ax, 0 
mov ds, ax 
mov cx, 18 
mov bx, [46Ch] 
WaitForAnotherChange: 
NoChange: 
mov ax, [46Ch] 
cmp ax, bx 
je NoChange 
mov bx, ax 
loop WaitForAnotherChange 

することは、あなたが小数に進数に変換する必要が小数を印刷する個々の数字を取得し、それらを印刷するには。番号を10で割り、残りの部分を収集します。例えば:

123:
10分の123:商12、余り3
12月10日:商1、余り2
1月10日:繰り返し10で割って商0、余り1

あなたは残りの部分の個々の数字を逆の順序で取得します:3,2,1。次に、DOS int 21h関数2(AHに2をロードし、文字のASCIIコードをDLにロードして、int 21hを実行します)を使用して印刷します。

​​命令を使用して、数字を変換せずに10進数で直接インクリメントする方法があります。

は、ここですべてを行うことができます方法は次のとおりです。あなたが先頭にゼロまたは最後の1秒の遅延が気に入らない場合は

; file: counter.asm 
; assemble: nasm.exe counter.asm -f bin -o counter.com 

bits 16 
org 0x100 

    mov ax, 0 ; initial number 
    mov cx, 256 ; how many numbers 

NextNumber: 
%if 1 ; change to 0 to use the DAA-based method 
    push ax 

    mov dx, 0 
    div word [ten] 
    push dx 

    mov dx, 0 
    div word [ten] 
    push dx 

    mov dx, 0 
    div word [ten] 
    push dx 

    pop dx 
    call PrintDigit 
    pop dx 
    call PrintDigit 
    pop dx 
    call PrintDigit 

    pop ax 

    call PrintNewLine 
    call Wait1s 

    inc ax 
%else 
    mov dl, ah 
    call PrintDigit 

    mov dl, al 
    shr dl, 4 
    call PrintDigit 

    mov dl, al 
    and dl, 0Fh 
    call PrintDigit 

    call PrintNewLine 
    call Wait1s 

    add al, 1 
    daa 
    adc ah, 0 
%endif 

    loop NextNumber 
    ret 

PrintDigit: 
    pusha 
    mov ah, 2 
    add dl, '0' 
    int 21h 
    popa 
    ret 

PrintNewLine: 
    pusha 
    mov dx, CRLF 
    mov ah, 9 
    int 21h 
    popa 
    ret 

Wait1s: 
    pusha 
    push ds 

    mov ax, 0 
    mov ds, ax 

    mov cx, 18 
    mov bx, [46Ch] 
WaitForAnotherChange: 
NoChange: 
    mov ax, [46Ch] 
    cmp ax, bx 
    je NoChange 
    mov bx, ax 
    loop WaitForAnotherChange 

    pop ds 
    popa 
    ret 

ten dw 10 
CRLF db 13,10,"$" 

、あなたは条件付きでそれらをスキップすることができます。

各命令の仕組みを説明しているIntelおよび/またはAMD x86 CPUのマニュアルをダウンロードしてください。それらを読みます。また、すべてのBIOSとDOS機能について説明しているRalf Brown's Interrupt Listをダウンロードしてください。あなたはI/Oを行うためにそれらのいくつかを知る必要があります。 HelpPCTechHelpもあり、前述のカウンタが存在するBIOS Data Areaのような多くのBIOSとDOSを便利に記述します。

+0

このコメントは@Alexのためのものです。あなたの寛大な助けてくれてありがとうございます。私はあなたが上記のコメントで言ったすべてを必ず読んでいます。ちょうど1つの質問ですが、プロセスを後退させるために投稿したコードを変更するのは難しいですか? (255から0まで)。 –

+0

助けてくれてありがとう@Alex –

+0

divベースのケースとdaaベースのケースの両方で、簡単で簡単です。 –

関連する問題