将十进制数转换为半字节的二进制形式

converts decimal number to its binary form in nibbles

这是我的代码,程序应要求输入 0-65,535 之间的数字,并应以半字节形式输出其十进制形式

.model small
.data
prompt db "Input an integer in the interval [0, 65535]: $", 0
number dw 0h
digitCounter db 0h
place_value dw 0h
number_of_bits dw 0h
two db 2

.stack 4096
.code
readInt proc
mov ah, 01h ; reads a character from the keybaord and loads it into the AL register
int 21h
ret 
readInt endp
; after readInt, AL has the integer itself, and AX has 0001 XXXX

newline proc
mov dl, 10
mov ah, 02h
int 21h
mov dl, 13
mov ah, 02h
int 21h
ret
newline endp

main proc

; Clearing data
mov ax, @data
mov ds, ax

; Start of main() proper
call newline
mov dx, offset prompt
mov ah, 09h
int 21h


DLOOP:
cmp digitCounter, 05h ; if we have already read 6 digits
je PROG_CONT ; we jump
call readInt ; puts the read character into the AH register     

cmp al, 0Dh 
je PROG_CONT

sub al, 30h ; after this point, the read character is sure to be an integer
; subtract 30h to it to get the actual value
mov ah, 0h ; makes the higher bits of ah 0
push ax ; pushes that integer into the stack
inc digitCounter
jmp DLOOP
PASSED_ONES:
dec digitCounter
add number, cx; ; adds the special case (the ones digit), to the number
cmp digitCounter, 0h
je ones_cont
inc place_value ; move to the next place value of the number (tens)
PROG_CONT:
pop cx ; pops the topmost element of the stack to register CX
cmp place_value, 0h ; at the beginning of the iteration this is known to be the ones digit
je PASSED_ONES
mov ax, 10 ; first we take the place value multiplier, e.g., tens - 10, hundreds - 100
mul place_value ; the result is stored in the DX:AX augmented register
mov bx, ax ; move the result to another register because we will use AX again for another multiplication
mov ax, cx ; now we move the popped value from the CX register to the AX register
mul bx ; AX = contains the digit, BX = contains the place value, DX:AX - result
add number, ax ; add the result to the number

mov ax, 0Ah ; first we take the place value multiplier, e.g., tens - 10, hundreds - 100
mul place_value
mov place_value, ax

dec digitCounter
jnz PROG_CONT

; after this point, the variable number contains the number itself 
ones_cont:  
mov ax, number

do:
div two ; after division, the remainder (the digit we want) is stored in the AH register
mov cl, ah ; we copy ah to bh so that we can use AX again
push cx ; the stack now has the digits of the number in reverse order, so when we pop it
; the first value we pop is the value of the largest place value
inc number_of_bits
mov ah, 0h ; clear out AH because AX will be used again for division
cmp al, 01h ; we continue dividing the quotient, which is stored in AL and if it's zero, we move on
jne do

continue:
inc number_of_bits
mov cx, 01h
push cx

mov ax, number_of_bits
jmp EVENING_OUT_DEM_BITS
APPEND_ZERO:
mov bl, 0h
push bx ; pushes the value '0' into the stack
inc number_of_bits
mov ax, number_of_bits
EVENING_OUT_DEM_BITS:
and ax, 03h ; we use bit masking to get the last two bits of 
; the binary number, and if both of them are zero, we know that
; the number is divisible by 4
; the answer, after the logical operation, is stored in the first operand
cmp ax, 0h 
jne APPEND_ZERO

; after this point, all of the zeros are even are ready to be printed to the console
call newline
jmp PRINTING_DEM_BITS

DECREASE_NUM_BITS:
dec number_of_bits
PRINTING_DEM_BITS:
pop cx ; pops the most significant bit and loads it into register DX
; now dh has the bit we want to print,
add cx, 30h ; to convert the number into it's ASCII form for printing
mov dx, cx
mov ah, 02h
int 21h 
cmp number_of_bits, 0h
jne DECREASE_NUM_BITS

; End of main() proper

; Returning to ms-dos
mov ax, 4c00h
int 21h

main endp
end main

每当我输入低于 512 的数字时,我都会正确显示,但当我输入大于或等于 512 的数字时,它会出现无限循环。 我是这里的新手,请帮忙。谢谢

请注意,div two 将破坏 ah,如果输入高于 512,您可能需要它。发生的情况是您有 AX=512,并且您似乎正在使用的字节大小的 div 会产生溢出,因为结果 256 不适合 8 位。大概是 DOS 忽略了生成的异常,这就是你没有意识到问题的原因。

无论如何,不​​推荐使用div到divide乘以2,简单的右移就足够了。如果你向左移动,你甚至可以得到正确顺序的数字。

div two 执行 'AL = AX / two'。如果结果不适合 AL (>255),您将得到 'divide overflow error'。如果 AX > 511,就会出现这种情况。将除法更改为 WORD 除法。

替换

...
.data
...
two db 2
...
.code
...
do:
div two ; after division, the remainder (the digit we want) is stored in the AH register
mov cl, ah ; we copy ah to bh so that we can use AX again
push cx ; the stack now has the digits of the number in reverse order, so when we pop it
; the first value we pop is the value of the largest place value
inc number_of_bits
mov ah, 0h ; clear out AH because AX will be used again for division
cmp al, 01h ; we continue dividing the quotient, which is stored in AL and if it's zero, we move on
jne do
...

来自

...
.data
...
two dw 2      ; WORD causes a WORD-division
...
.code
...
do:
xor dx, dx
div two         ; DX:AX / two -> AX, remainder DX
mov cx, dx
push cx ; the stack now has the digits of the number in reverse order, so when we pop it
; the first value we pop is the value of the largest place value
inc number_of_bits
cmp ax, 01h
jne do
...

其他地方有问题:512d 不是 0010000000001b。