Jea*_*ini 5 x86 assembly dos bios nasm
我正在使用NASM 16 BITS.我正在尝试做一个简单的汇编代码,打印0到255之间的数字,每个数字之间间隔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
Run Code Online (Sandbox Code Playgroud)
我不确定如何在屏幕上打印ax的值,以及如何等待1秒(将它们放在代码中的注释中).
在PC BIOS维护和更新的段0偏移46Ch(或者在段40h,关闭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
Run Code Online (Sandbox Code Playgroud)
要打印十进制数,您需要将二进制数转换为十进制数,获取单个数字并打印它们.您将数字除以10并收集余数.例如:
123:
123/10:商12,余数3
12/10:商1,余数2
1/10:商0,余数1
通过重复除以10,您可以按相反的顺序得到余数中的各个数字:3,2,1.然后用DOS int 21h函数2打印它们(加载2进入AH,加载字符的ASCII码进入DL,执行int 21h).
另一种非常适合您的问题的变体是使用该DAA指令直接以十进制递增数字而不进行任何转换.
以下是这一切的完成方式:
; 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,"$"
Run Code Online (Sandbox Code Playgroud)
如果您不喜欢前导零或最后1秒延迟,则可以有条件地跳过它们.
下载描述每条指令如何工作的Intel和/或AMD x86 CPU手册.读它们.另外,下载Ralf Brown's Interrupt List,描述每个BIOS和DOS功能.你需要知道其中一些做I/O. 也有HelpPC和TechHelp它可以方便地描述像许多BIOS和DOS的事情BIOS Data Area上述计数器住在哪里.