显示时间大会 [英] Displaying Time in Assembly

查看:237
本文介绍了显示时间大会的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好我尝试显示实际时间时/分/秒,这是我的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的FizzBu​​zz

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆