2015-09-25 101 views
2

這裏是我的代碼,程序應該要求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的數字時,它有一個無限循環。 我是新手,請幫忙。謝謝

+0

學習使用調試器來遍歷代碼。除此之外,'cmp al,01h'的評論'如果它是零'是非常可疑的。 – Jester

+1

如果您在x86上使用其中一個鮮爲人知的BCD相關指令,也有一些小技巧。想到「AAA」。不知何故,我懷疑你的教授會對這樣的解決方案感到滿意。 –

+0

@Jester我只是忘了改變它曾經的評論cmp al,0h – rjk

回答

2

div two執行'AL = AX/2'。如果結果不符合AL(> 255),則會出現「分割溢出錯誤」。如果AX> 511,則是這種情況。將分區更改爲WORD分區。

通過

... 
.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 
... 

更換

... 
.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 
... 

有其他地方的一個問題:512D不0010000000001b。

2

請注意,div two將破壞ah,如果輸入大於512,則可能需要該值。會發生什麼是AX=512,並且您似乎正在使用的字節大小的div會產生溢出,因爲結果256不適合8位。據推測DOS會忽略生成的異常,這就是爲什麼你沒有意識到這個問題。

在任何情況下,不建議使用div除以2,只需簡單的換檔權即可。如果你左移,你甚至可以按照正確的順序得到數字。

+0

謝謝!這非常有幫助! – rjk

相關問題