显示时间大会 [英] Displaying Time in Assembly
问题描述
您好我尝试显示实际时间时/分/秒,这是我的code样品:</ P>
Hello im trying to display the actual time hours/minutes/seconds this is my code sample:
MOV AH, 2Ch
INT 21h
MOV AH, 0Eh
MOV AL, CH
INT 10h
MOV AL, 3Ah
INT 10h
MOV AL, CL
INT 10h
MOV AL, 3Ah
INT 10h
MOV AL, DH
INT 10h
ret
在这里,你能有什么本质上的控制台显示
Here you can se what the console is displaying
推荐答案
查看的 86 标签维基指令集参考手册,和许多很好的参考资料的链接和教程。
See the x86 tag wiki for the instruction set reference manual, and many good links to reference material and tutorials.
这需要足够的code到一个整数分解成ASCII数字,你应该因子它成一个函数。
It takes enough code to split up an integer into ASCII digits that you should factor it out into a function.
这是@霍布斯的print2Digits功能的优化和bugfixed版本。 (我也bugfixed在他的回答版本,所以它是正确的太多,但离开这一个优化)。
This is an optimized and bugfixed version of @hobbs's print2Digits function. (I also bugfixed the version in his answer, so it's correct too, but left the optimizations for this one).
print2Digits:
;; input in AL (0-99).
;; clobbers AX and DX
cbw ; zero AH. Sign-extending AL does the job because AL is only allowed to be 0-99.
; omit this step if you can easily have the caller use the full AX, i.e. zero AH for us
mov dl, 10
div dl ; quotient in AL(first (high) digit), remainder in AH(second (low) digit)
add ax, 0x3030 ; add '0' to al and ah at the same time.
mov dl, ah ; save the 2nd digit
mov ah, 0x0E ; DOS system call number for printing a single character
int 0x10 ; print high digit first. Doesn't clobber anything, so AH still holds 0x0E after
mov al, dl
int 0x10 ; print the low digit 2nd
ret
由于我们使用 DIV
为一个整数分成两个base10数字,我们需要啊
为零。我们可以保存 CBW
如果主叫方的确 MOVZX斧,CH
什么的,零啊
。
Since we used div
to split an integer into two base10 digits, we need ah
to be zero. We could save the cbw
if the caller did movzx ax, ch
or something, to zero ah
.
(除8086不具有 MOVZX
,所以你必须真正异斧,斧
/ MOV人,CH
)
(Except that 8086 doesn't have movzx
, so you'd have to actually xor ax,ax
/ mov al, ch
.)
有一个DOS系统调用用于打印整个字符串,所以你可以字符存储到一个小的缓冲区,全部打印出来了,就象我在这个<一做href=\"http://stackoverflow.com/questions/28334034/fizzbuzz-in-assembly-segmentation-fault/37494090#37494090\">AMD64 Linux的FizzBuzz
There's a DOS system call for printing a whole string, so you could store characters into a small buffer and print them all at once, like I do in this AMD64 Linux FizzBuzz
这也是可以使用 AAM
10 分AL(而不是AX),避免了零AH第一。这比 DIV R8
目前Intel和AMD的CPU速度稍快。然而,它把结果相反的寄存器从 DIV
,其中 AAM
后意味着额外的说明。这平衡了对 MOV DL保存,10
和 CBW
It's also possible to use aam
to divide AL (instead of AX) by 10, avoiding the need to zero AH first. It's slightly faster than div r8
on current Intel and AMD CPUs. However, it puts the results in the opposite registers from div
, which means extra instructions after the aam
. This balances out the saving on the mov dl, 10
and cbw
print2Digits:
;; input in AL (0-99). (Ignores AH because we use AAM instead of div)
;; clobbers AX and DX
aam ; like `div` by 10, but with the outputs reversed, and input from AL only
; quotient in AH (high digit), remainder in AL(low digit). (Opposite to div)
add ax, 0x3030 ; add '0' to al and ah at the same time.
mov dl, al ; save the low digit
mov al, ah ; print high digit first
mov ah, 0x0E ; DOS system call number for printing a single character
int 0x10 ; print first digit. Doesn't clobber anything, so AH still holds 0x0E after
mov al, dl
int 0x10 ; print second digit
ret
即使我们要存储一个字符串(和打一个电话,一个打印字符串函数或系统调用),我们不得不换人啊AX存储到内存中之前(如 XCHG人啊
,或更有效地在现代硬件上, ROL斧头,8
)。 DIV
产生他们在正确的顺序。
Even if we wanted to store to a string (and make one call to a print-string function or system call), we'd have to swap al and ah before storing AX to memory (e.g. xchg al,ah
, or more efficiently on modern hardware, rol ax,8
). div
produces them in the right order.
386,其中的32位地址大小可,我们可以节省一个指令:
For 386 where 32bit address-size is available, we can save one instruction:
lea dx, [eax + 0x3030] ; need a 32bit addressing mode to use eax as a source reg. Adds '0' to both digits at once, with a different destination.
mov al, dh
的 LEA
需要一个地址大小preFIX和2个字节的MOD / RM,和一个32位的位移,所以它在code严重损失-size,但它确实节省一个指令。
The lea
needs an address-size prefix and a 2-byte mod/rm, and a 32bit displacement, so it loses badly on code-size, but it does save one instruction.
使用 LEA
后 DIV
从 EAX
阅读写斧
将可能是对的SandyBridge-系列CPU更快,尤其。 Haswell的和以后,但在Intel pre-SNB,部分寄存器延迟将使其更好地使用具有单独的插件和MOV指令纯16位版本。
Using lea
to read from eax
after div
writes ax
will probably be faster on Sandybridge-family CPUs, esp. Haswell and later, but on Intel pre-SnB, the partial register stall will make it better to use the pure 16bit version with separate add and mov instructions.
这篇关于显示时间大会的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!