The procedure out_a_nibble appears simple but it involves quite a lot
of thinking. Let's see how it should work to fit within the code of
stack_to_string. The word, where to extract the nibbles from, is already in BX. CX changes
from 4 to 1 and could be used as a selector of the nibble. The procedure
coming after it expects the input to be in the low nibble of AL (bit 0 to bit
3) and will return the corresponding ASCII code in AL (bit7 to bit0). As a
consequence, the procedure out_a_nibble must deliver output in the form
AL = 0000???? in binary. Now suppose that BX = 0xABCD so the most
significant nibble is 0xA and the less significant nibble is 0xD. The question
is: which selection order shall I use? stack_to_string stores the bytes
from left to right when writing the string and the register DI increases
automatically every time. So it's better to select the nibbles in BX also from
left to right. As CX changes from 4 to 1, the logical consequence is that the
selected nibble in AL changes from 0xA to 0xD. Since we want our output to be
available in AL then the best way to proceed is to copy the value of BX into
AX and then perform a right shift that places the desired nibble in the
position from bit 3 to bit 0 of AL. Another constrain is that a right shift of
any bit different from 1 can only be performed specifying the amount in CL1, but CX already holds the value of the counter. Having considered all of
these constrains I came up with the following code which, I think, is ok. Of
course and as usual, you are encouraged to think differently and to try
your own way.
out_a_nibble - final
out_a_nibble:
################################################################################
#
# This procedure returns in AL (bit0 to bit3) the value of the selected nibble
# in BX. The selection is done depending on the value in CX
#
# INPUT: BX = word to select the nibble from
# CX = nibble selection inside the word in BX
# OUTPUT: AL = selected nibble
# REGISTER USAGE: DX
# THIS ONE CALLS: ---
#
# EXAMPLE: BX: CX: AX:
# ABCD 0001 000D
# ABCD 0002 000C
# ABCD 0003 000B
# ABCD 0004 000A
#
################################################################################
mov ax, bx # it copies the value in AX.
mov dx, cx # store the value of CX to resume it before exit.
# SHR instruction must use CL register:
# before shift | after shift
# -------------+--------------
# ABC[D] | ABC[D] --> 0 bits shift
# AB[C]D | 0AB[C] --> 4 bits shift
# A[B]CD | 00A[B] --> 8 bits shift
# [A]BCD | 000[A] --> 12 bits shift
#
# Relationship table for the value of shift:
# index | value of shift
# x | y = f(x)
# ------+----------
# 4 | 12
# 3 | 8
# 2 | 4
# 1 | 0
#
# Relationship formula for the value of shift:
# y = 4*(x-1) --> CL = 4*(CX - 1) desired target
dec cx # CX = CX - 1 --> CL = (CX - 1) step 1
shl cx, 1 # CX = 2*CX --> CL = 2*(CX - 1) step 2
shl cx, 1 # CX = 2*CX --> CL = 2*2*(CX - 1) final step
shr ax, cl # select the nibble
and ax, 0x000f # mask remaining bits
mov cx, dx # restore CX before return
#####################
# end of procedure
#####################
ret
Comments
Post a Comment