mov ah, 2 and int 1ah - 错误的打印时间?
mov ah, 2 and int 1ah - wrong print hours?
所以,我刚刚从 中找到了代码。我正在尝试以小时为单位打印当前时间,但输出不是预期的。
这是 wroing output
的屏幕截图
预期输出是当前时间:14 16 (secs)
BITS 16
ORG 0x7C00
_start:
mov ax, 07C0h
add ax, 288
mov ss, ax ; ss = stack space
mov sp, 4096 ; sp = stack pointer
mov ax, 07C0h
mov ds, ax ; ds = data segment
call time
call cvthrs
call cvtmin
call cvtsec
call dsptime
cli
endloop:
hlt
jmp endloop
time:
;Get time from the system
mov ah,02h
int 1Ah
;ret
;CH - Hours
;CL - Minutes
;DH - Seconds
cvthrs:
;Converts the system time from BCD to ASCII
mov bh,ch ;copy contents of hours (ch) to bh
shr bh, 4
add bh,30h ;add 30h to convert to ascii
mov [tmfld],bh
mov bh,ch
;and bh,0fh
add bh,30h
mov [tmfld + 1],bh
ret
cvtmin:
mov bh,cl ;copy contents of minutes (cl) to bh
shr bh, 4
add bh,30h ;add 30h to convert to ascii
mov [tmfld + 3],bh
mov bh,cl
and bh,0fh
add bh,30h
mov [tmfld + 4],bh
ret
cvtsec:
mov bh,dh ;copy contents of seconds (dh) to bh
shr bh, 4
add bh,30h ;add 30h to convert to ascii
mov [tmfld + 6],bh
mov bh,dh
and bh,0fh
add bh,30h
mov [tmfld + 7],bh
ret
tmfld: db '00:00:00'
dsptime:
;Display the system time
mov ah,13h ;function 13h (Display String)
mov al,0 ;Write mode is zero
mov bh,0 ;Use video page of zero
mov bl,0x0f;Attribute
mov cx,8 ;Character string is 8 long
mov dh,5 ;position on row 5
mov dl,0;and column 0
push ds ;put ds register on stack
pop es ;pop it into es register
lea bp,[tmfld] ;load the offset address of string into BP
int 10H
ret
使用 QEMU 编译和运行:
nasm time.asm -fbin -o time.img
qemu-system-i386 -drive format=raw,file=./time.img
如何解决这个问题?
输出不显示当前时间,因为您给 BIOS.WriteString 函数 13h 的 ES:BP
中的远指针是错误的。
问题在于 ORG 0x7C00
指令以及您如何设置 DS
段寄存器。
当您指定 7C00h 的原点时,您指示汇编器将代码的第一个字节视为驻留在 7C00h 的偏移地址处。这意味着段开始 和 DS
应该指向 的 0000h 的偏移地址现在在内存中很低。您应该在 DS
中加载的唯一正确值是 0。
也可以指定 ORG 0000h
,然后在 DS
段寄存器中加载的正确值将是 07C0h(就像您所做的那样)。
;ret in time
;and bh,0fh in cvthrs
为了获得正确的结果,您需要在 time 和 cvthrs 子例程中取消注释这些行。
这是一个带有一些改进的快速重写:
BITS 16
ORG 0000h
_start:
mov ax, 07C0h
mov ds, ax
add ax, 32
mov ss, ax ; ss = 07E0h
mov sp, 4096 ; sp = stack pointer
call time
mov al, ch ; hours
call cvt ; -> AX
mov [tmfld + 0], ax
mov al, cl ; minutes
call cvt ; -> AX
mov [tmfld + 3], ax
mov al, dh ; seconds
call cvt ; -> AX
mov [tmfld + 6], ax
call dsptime
cli
endloop:
hlt
jmp endloop
time: ; Get time from the system
mov ah, 02h
int 1Ah ; BIOS.ReadRealTimeClock
jnc OK
mov cx, 9999h ; Displays 99:99:99 if clock is malfunctioning
mov dh, 99h
OK:
ret
;CH - Hours
;CL - Minutes
;DH - Seconds
cvt:
mov ah, al
shr al, 4
and ah, 0Fh
add ax, 3030h
ret
tmfld: db '00:00:00'
dsptime:
;Display the system time
mov ah, 13h ;function 13h (Display String)
mov al, 0 ;Write mode is zero
mov bh, 0 ;Use video page of zero
mov bl, 0Fh ;Attribute
mov cx, 8 ;Character string is 8 long
mov dh, 5 ;position on row 5
mov dl, 0 ;and column 0
push ds ;put ds register on stack
pop es ;pop it into es register
mov bp, tmfld ;load the offset address of string into BP
int 10h
ret
times 510-($-$$) db 0
dw 0AA55h
如果使用mov
指令加载tmfld的地址,它会缩短1个字节。
您可以通过将对相关字节大小寄存器的加载组合为相应字大小寄存器的 1 次加载来进一步改进这一点:
例如变化:
mov dh, 5 ;position on row 5
mov dl, 0 ;and column 0
进入
mov dx, 0500h ; DH=5 (row), DL=0 (column)
所以,我刚刚从
这是 wroing output
的屏幕截图预期输出是当前时间:14 16 (secs)
BITS 16 ORG 0x7C00 _start: mov ax, 07C0h add ax, 288 mov ss, ax ; ss = stack space mov sp, 4096 ; sp = stack pointer mov ax, 07C0h mov ds, ax ; ds = data segment call time call cvthrs call cvtmin call cvtsec call dsptime cli endloop: hlt jmp endloop time: ;Get time from the system mov ah,02h int 1Ah ;ret ;CH - Hours ;CL - Minutes ;DH - Seconds cvthrs: ;Converts the system time from BCD to ASCII mov bh,ch ;copy contents of hours (ch) to bh shr bh, 4 add bh,30h ;add 30h to convert to ascii mov [tmfld],bh mov bh,ch ;and bh,0fh add bh,30h mov [tmfld + 1],bh ret cvtmin: mov bh,cl ;copy contents of minutes (cl) to bh shr bh, 4 add bh,30h ;add 30h to convert to ascii mov [tmfld + 3],bh mov bh,cl and bh,0fh add bh,30h mov [tmfld + 4],bh ret cvtsec: mov bh,dh ;copy contents of seconds (dh) to bh shr bh, 4 add bh,30h ;add 30h to convert to ascii mov [tmfld + 6],bh mov bh,dh and bh,0fh add bh,30h mov [tmfld + 7],bh ret tmfld: db '00:00:00' dsptime: ;Display the system time mov ah,13h ;function 13h (Display String) mov al,0 ;Write mode is zero mov bh,0 ;Use video page of zero mov bl,0x0f;Attribute mov cx,8 ;Character string is 8 long mov dh,5 ;position on row 5 mov dl,0;and column 0 push ds ;put ds register on stack pop es ;pop it into es register lea bp,[tmfld] ;load the offset address of string into BP int 10H ret
使用 QEMU 编译和运行:
nasm time.asm -fbin -o time.img
qemu-system-i386 -drive format=raw,file=./time.img
如何解决这个问题?
输出不显示当前时间,因为您给 BIOS.WriteString 函数 13h 的 ES:BP
中的远指针是错误的。
问题在于 ORG 0x7C00
指令以及您如何设置 DS
段寄存器。
当您指定 7C00h 的原点时,您指示汇编器将代码的第一个字节视为驻留在 7C00h 的偏移地址处。这意味着段开始 和 DS
应该指向 的 0000h 的偏移地址现在在内存中很低。您应该在 DS
中加载的唯一正确值是 0。
也可以指定 ORG 0000h
,然后在 DS
段寄存器中加载的正确值将是 07C0h(就像您所做的那样)。
;ret in time ;and bh,0fh in cvthrs
为了获得正确的结果,您需要在 time 和 cvthrs 子例程中取消注释这些行。
这是一个带有一些改进的快速重写:
BITS 16
ORG 0000h
_start:
mov ax, 07C0h
mov ds, ax
add ax, 32
mov ss, ax ; ss = 07E0h
mov sp, 4096 ; sp = stack pointer
call time
mov al, ch ; hours
call cvt ; -> AX
mov [tmfld + 0], ax
mov al, cl ; minutes
call cvt ; -> AX
mov [tmfld + 3], ax
mov al, dh ; seconds
call cvt ; -> AX
mov [tmfld + 6], ax
call dsptime
cli
endloop:
hlt
jmp endloop
time: ; Get time from the system
mov ah, 02h
int 1Ah ; BIOS.ReadRealTimeClock
jnc OK
mov cx, 9999h ; Displays 99:99:99 if clock is malfunctioning
mov dh, 99h
OK:
ret
;CH - Hours
;CL - Minutes
;DH - Seconds
cvt:
mov ah, al
shr al, 4
and ah, 0Fh
add ax, 3030h
ret
tmfld: db '00:00:00'
dsptime:
;Display the system time
mov ah, 13h ;function 13h (Display String)
mov al, 0 ;Write mode is zero
mov bh, 0 ;Use video page of zero
mov bl, 0Fh ;Attribute
mov cx, 8 ;Character string is 8 long
mov dh, 5 ;position on row 5
mov dl, 0 ;and column 0
push ds ;put ds register on stack
pop es ;pop it into es register
mov bp, tmfld ;load the offset address of string into BP
int 10h
ret
times 510-($-$$) db 0
dw 0AA55h
如果使用mov
指令加载tmfld的地址,它会缩短1个字节。
您可以通过将对相关字节大小寄存器的加载组合为相应字大小寄存器的 1 次加载来进一步改进这一点:
例如变化:
mov dh, 5 ;position on row 5
mov dl, 0 ;and column 0
进入
mov dx, 0500h ; DH=5 (row), DL=0 (column)