汇编语言转换为进位标志
Assembly Language Shift into Carry Flags
我目前有一个作业,我必须用汇编语言编写代码,你需要用户输入以获得一个 4 位十六进制值并将其转换为二进制,然后在你获得二进制值后,你必须将其转换为月日和年,其中前 7 位是年,接下来的四位是月,最后 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
如果我没理解错的话,在 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? ) 指令,这些指令有点 "advanced" 并且可以为您节省我之前提到的那些基础知识的一些 2-3 指令组合。所以你可以安全地忽略它们,只要你完全理解那些基本的并且可以根据需要使用它们来弯曲任何东西。
我目前有一个作业,我必须用汇编语言编写代码,你需要用户输入以获得一个 4 位十六进制值并将其转换为二进制,然后在你获得二进制值后,你必须将其转换为月日和年,其中前 7 位是年,接下来的四位是月,最后 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
如果我没理解错的话,在 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? ) 指令,这些指令有点 "advanced" 并且可以为您节省我之前提到的那些基础知识的一些 2-3 指令组合。所以你可以安全地忽略它们,只要你完全理解那些基本的并且可以根据需要使用它们来弯曲任何东西。