0

我目前有一个任务,我必须用汇编语言编写代码,在其中你接受用户输入以获取 4 位十六进制值并将其转换为二进制,然后在获得二进制值后,你必须将其转换为月日和年,其中前 7 位数字是年份,接下来的 4 位是月份,最后 5 位是日期。

我将所有内容都转换为二进制,并且知道如何将其从二进制转换为年、月和日的正常整数值。当我运行我的代码时,输​​出是0/0/0. 我不确定这是我在换档时搞砸的地方还是其他什么地方。你们能看一下并给我一个关于在哪里更正的意见吗?在我粘贴的代码中,我只输入了 calcYear 并认为我可以解决这个问题,然后从那里开始处理其余部分。

我的代码:

firstLine:

    call crlf
    mov si, offset programOne
    mov cx, programOneLen
    call putStrng       ;displays 'Program by Joe Remaklus'

    call crlf
    call crlf

    call inputVal   ;prompt for hex input
    call putBin ;display the value in AX as binary
    call crlf
    call calcYear   ;display the year of the first 7 binary digits.
    mov si, offset slash
    mov cx, slashLen
    call putStrng
    call calcMonth  ;display the month of the next 4 binary digits.
    mov si, offset slash
    mov cx, slashLen
    call putStrng
    call calcDay    ;display the day of the next 5 binary digits.
    call crlf

    call inputVal
    call putBin






    mov ah,04c
    int 021




prompt db 'Enter a 4-digit hex value'

lenPrompt = $-prompt


inputVal:

    push si, cx

    mov  si, offset prompt

    mov  cx, lenPrompt

    call putStrng

    call crlf

    call getHex

    call crlf

    pop  cx, si

    ret
;---------------------------------------------------------------

putBin:

    push ax, cx, dx

    mov  cx, 16     ;number of bits to display

  putBinLoopTop:

    mov  dl, '0'        ;assume bit to display is zero

    shl  ax, 1      ;shift bit to display into Carry Flag

    jnc  putBinSkipInc  ;if the top bit was zero skip the inc

    inc  dl         ;else inc DL to '1'

  putBinSkipInc:

    call putChar        ;display the character in DL

    loop putBinLoopTop  ;continue until 16 bits are displayed

    pop  dx, cx, ax

    ret
;---------------------------------------------------------------

calcYear:

    mov year, 0

    mov si, 0

    shl ax, 1
    adc si, 0
    iMul onetwoeight
    add year, si
    mov si, 0 

    shl ax, 1
    adc si, 0
    iMul sixfour
    add year, si
    mov si, 0

    shl ax, 1
    adc si, 0
    iMul threetwo
    add year, si
    mov si, 0

    shl ax, 1
    adc si, 0
    iMul sixteen
    add year, si
    mov si, 0

    shl ax, 1
    adc si, 0
    iMul eight
    add year, si
    mov si, 0


    shl ax, 1
    adc si, 0
    iMul four
    add year, si
    mov si, 0


    shl ax, 1
    adc si, 0
    iMul two
    add year, si
    mov si, 0


    shl ax, 1
    adc si, 0
    iMul one
    add year, si
    mov si, year
    add si, 1980
    call putPos
ret
4

1 回答 1

1

如果我理解正确,在输入 calcYear 时,您的“ax”在二进制中看起来像这样:yyyy yyym mmmd dddd

并且您想将这些值提取回普通数字。我想我可以理解你对“calcYear”的想法,但很抱歉没有费心去尝试完全理解并修复它。如果您仍然好奇,只需使用调试器单步执行每条指令,看看它往南走。

相反,我将向您展示如何以不同的方式思考这个问题。

让我们尝试挖掘并理解这一点:

    ; ax is encoded as this: yyyy yyym mmmd dddd
    push ax
    push ax ; store the encoded value at stack twice
    ; extract "day" value
    and ax,01Fh  ;only "d" bits will survive
    mov [day],ax
    ; extract "month" value
    pop ax ; restore encoded input
    shr ax,5 ; shift ax by number of "d" bits
    and ax,0Fh ; only shifted "m" bits
    mov [month],ax
    ; extract "year" value
    pop ax ; restore encoded input
    shr ax,5+4 ; shift ax by number of "d" and "m" bits
    ; no need to "and", as "shr" did fill upper bits by zeroes
    add ax,1980 ; so "0" encoded year is 1980? (deducted from OP source)
    mov [year],ax
    ret

我希望这会给你一些新的想法,如何使用特定的位数。请记住,and/or可以很好地掩盖您感兴趣的事物,并且shr/sar/sal/shl/ror/rol/rcr/...可以很好地将其放在所需的位置。xor可以用来对结果进行一些修补(如果需要),test就像and只更新标志寄存器,然后还有一些面向位的 x386+(或 486?)指令,它们有点“高级”,可以为您节省一些 2我之前提到的那些基础知识的 -3 指令组合。所以你可以放心地忽略它们,只要你完全理解那些基本的,并且可以随心所欲地弯曲任何东西。

于 2016-04-28T11:32:03.510 回答