因此,我剛剛從這個問題中找到代碼。我試圖列印以小時為單位的當前時間,但輸出結果不理想。
這是wroing output的截屏。
預期的輸出是當前時間:14 16 (secs)
BITS 16
ORG 0x7C00
開始。
mov ax, 07C0h
添加 ax, 288
mov ss, ax ; ss = 堆疊空間
mov sp, 4096 ; sp = 堆疊指標
mov ax, 07C0h
mov ds, ax ; ds = 資料段
呼叫時間
呼叫cvthrs
呼叫cvtmin
呼叫cvtsec
呼叫dsptime
呼叫
endloop:
hlt
jmp endloop
時間。
;從系統中獲取時間
mov ah,02h
int 1Ah
;ret
;CH - 小時
;CL - 分鐘
;DH - 秒
cvthrs:
;將系統時間從BCD轉換為ASCII碼
mov bh,ch ;將小時(ch)的內容復制到bh中
bh,4
add bh,30h ;添加30h以轉換為ASCII碼。
mov [tmfld],bh
mov bh,ch
;和bh,0fh
添加bh,30h
mov [tmfld 1],bh
回傳
cvtmin:
mov bh,cl ;將分鐘(cl)的內容復制到bh中
縮小bh,4
add bh,30h ;添加30h以轉換為ascii格式。
mov [tmfld 3],bh
mov bh,cl
和bh,0fh
添加bh,30h
mov [tmfld 4],bh
檢索
cvtsec:
mov bh,dh ;復制秒的內容(dh)到bh
縮小bh,4
add bh,30h ;添加30h以轉換為ascii格式。
mov [tmfld 6],bh
mov bh,dh
和bh,0fh
添加bh,30h
mov [tmfld 7],bh
檢索
tmfld: db '00:00:00' 。
dsptime。
;顯示系統時間
mov ah,13h ;功能 13h (顯示字串)
mov al,0 ;寫入模式為零
mov bh,0 ;使用視頻頁面為零
mov bl,0x0f;屬性
mov cx,8 ;字串為8長
mov dh,5 ;位置在第5行
mov dl,0;和第0列
push ds ;把ds暫存器放到堆疊上
pop es ;將其彈入es暫存器
lea bp,[tmfld] ;將字串的偏移地址載入BP中
int 10H
檢索
使用QEMU進行編譯和運行:
nasm time.asm -fbin -o time.img
qemu-system-i386 -drive format=raw,file=./time.img
如何解決這個問題?
uj5u.com熱心網友回復:
輸出沒有顯示當前時間,因為你給BIOS.WriteString函式13h的ES:BP中的遠指標是錯誤的。
問題出在ORG 0x7C00指令和你如何設定DS段暫存器。
當你指定一個7C00h的原點時,你指示匯編程式認為你的代碼的第一個位元組位于7C00h的偏移地址。這意味著段開始的偏移地址0000h和DS應該指向的地方現在在記憶體中已經很遠了。你應該在DS中加載的唯一正確的值是0.
也可以指定ORG 0000h,然后在DS段暫存器中加載的正確值將是07C0h(就像你做的那樣)。
;ret in time ;和cvthrs中的bh,0fh
為了獲得正確的結果,你需要在你的time和cvthrs子程式中取消注釋這幾行。
這是一個快速的重寫,有一些改進:
這是一個快速的重寫,有一些改進。
BITS 16
ORG 0000h
開始。
mov ax, 07C0h
mov ds, ax
添加ax,32
mov ss, ax ; ss = 07E0h
mov sp, 4096 ; sp = 堆疊指標
呼叫時間
mov al, ch ; hours
呼叫cvt ; -> AX
mov [tmfld 0], ax
mov al, cl ; minutes
Call cvt ; -> AX
移動 [tmfld 3], ax
mov al, dh ; seconds
呼叫cvt ; -> AX
移動 [tmfld 6], ax
呼叫 dsptime
cli
endloop。
hlt
jmp endloop
time: ; 從系統中獲取時間
mov ah, 02h
int 1Ah ; BIOS.ReadRealTimeClock
jnc OK
mov cx, 9999h ; 如果時鐘出現故障,顯示 99:99:99
mov dh, 99h
OK。
回傳
;CH - 小時
;CL - 分鐘
;DH - 秒
cvt:
mov ah, al
縮小al,4
and ah, 0Fh
添加ax,3030h
檢索
tmfld: db '00:00:00'.
dsptime。
;顯示系統時間
mov ah, 13h ;功能 13h (顯示字串)
mov al, 0 ;寫入模式為零
mov bh, 0 ;使用視頻頁面為零
mov bl, 0Fh ;屬性
mov cx, 8 ;字串為8長
mov dh, 5 ;位置在第5行
mov dl, 0 ;和第0列
push ds ;把ds暫存器放到堆疊上
pop es ;將其彈入es暫存器
mov bp, tmfld ;將字串的偏移地址加載到BP中。
int 10h
檢索
times 510-($-$$) db 0
dw 0AA55h
如果你用mov指令加載tmfld的地址,它將縮短1個位元組。
你可以通過把對相關的位元組大小的暫存器的加載合并為對相應的字大小的暫存器的1次加載來進一步改進:
例如,改變對相關的位元組大小的暫存器的加載為1次加載。
例如,改變:
mov dh, 5 ;位置在第5行。
mov dl, 0 ;和第0列
變成
mov dx, 0500h ; DH=5 (行), DL=0 (列)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/320411.html
標籤:
上一篇:int8陣列與標量的快速乘法
