为什么下面的8086汇编代码只能显示2559以内的数字?
Why does the following 8086 assembly code only display numbers up to 2559?
我想做什么?
我想从用户那里得到一个16位的数字并在控制台上打印它。
问题是什么?
我的代码工作正常如果输入的数字小于 2600 但当我输入 2600 时它显示“40”,对于 2601 显示“41”等等。它不应该显示最多 65535 的数字吗?因为我把值存入bx
寄存器里,它是16位的,最多能存65535。那为什么只能存2559?
我的代码:
.model small
.data
msg db 10,13,'Enter a 16bit number: $'
newline db 10,13,'$'
.code
main:
mov ax, @data
mov ds, ax
mov cl, 10
mov bx, 0
mov ah, 09h
lea dx, msg
int 21h
call get16bitNum
mov ah, 09h
lea dx, newline
int 21h
mov ax, '$'
push ax
mov ax, bx
store:
div cl
cmp al, 0
mov bh, 0
mov bl, ah
push bx
je continue
mov ah, 0
jmp store
continue:
pop ax
cmp ax, '$'
je ext
mov bx, ax
mov ah, 02h
mov dx, bx
add dx, 48
int 21h
jmp continue
ext:
mov ah, 04ch
int 21h
proc get16bitNum
aggregate:
mov ah, 01h
int 21h
cmp al, 13
je return
mov ah, 0
sub al, 48
mov dx, bx
mov bx, ax
mov ax, dx
mul cl
add bx,ax
jmp aggregate
return:
ret
endp
end main
8位div
产生8位商和余数。
当您将 2600 除以 10 时,您会得到一个 8 位的商,丢失更高的位。
你应该使用16位除法。
您实际上并没有检索到 16 位数字!
您将所需的输入保留在 BX
中,因此您需要将整个 BX
乘以 10。您使用 word 大小的乘法 [=30] =].
proc get16bitNum
aggregate:
mov ah, 01h
int 21h
cmp al, 13
je return
mov ah, 0
sub al, 48 ;AX is 0 to 9
xchg ax, bx ;New digit temporarily in BX
mov cx, 10
mul cx ;Product is in DX:AX, but we won't use DX!
add bx ,ax ;Add new digit
jmp aggregate
return:
ret
您没有显示 16 位数字
将数字转换为文本的过程肯定需要使用字大小划分。
有关如何执行此操作的精彩解释,请参阅最近的 post Displaying numbers with DOS。它非常详细地解释了您需要了解的有关转换数字的所有信息。它甚至使用相同的技术在堆栈中压入一些值(你为此使用了 $ 字符)来知道数字在哪里结束。
ps。如果您觉得 the linked post 中的信息有用,请毫不犹豫地点赞它。 (当然也希望我的回答对你有用!)
我想做什么?
我想从用户那里得到一个16位的数字并在控制台上打印它。
问题是什么?
我的代码工作正常如果输入的数字小于 2600 但当我输入 2600 时它显示“40”,对于 2601 显示“41”等等。它不应该显示最多 65535 的数字吗?因为我把值存入bx
寄存器里,它是16位的,最多能存65535。那为什么只能存2559?
我的代码:
.model small
.data
msg db 10,13,'Enter a 16bit number: $'
newline db 10,13,'$'
.code
main:
mov ax, @data
mov ds, ax
mov cl, 10
mov bx, 0
mov ah, 09h
lea dx, msg
int 21h
call get16bitNum
mov ah, 09h
lea dx, newline
int 21h
mov ax, '$'
push ax
mov ax, bx
store:
div cl
cmp al, 0
mov bh, 0
mov bl, ah
push bx
je continue
mov ah, 0
jmp store
continue:
pop ax
cmp ax, '$'
je ext
mov bx, ax
mov ah, 02h
mov dx, bx
add dx, 48
int 21h
jmp continue
ext:
mov ah, 04ch
int 21h
proc get16bitNum
aggregate:
mov ah, 01h
int 21h
cmp al, 13
je return
mov ah, 0
sub al, 48
mov dx, bx
mov bx, ax
mov ax, dx
mul cl
add bx,ax
jmp aggregate
return:
ret
endp
end main
8位div
产生8位商和余数。
当您将 2600 除以 10 时,您会得到一个 8 位的商,丢失更高的位。
你应该使用16位除法。
您实际上并没有检索到 16 位数字!
您将所需的输入保留在 BX
中,因此您需要将整个 BX
乘以 10。您使用 word 大小的乘法 [=30] =].
proc get16bitNum
aggregate:
mov ah, 01h
int 21h
cmp al, 13
je return
mov ah, 0
sub al, 48 ;AX is 0 to 9
xchg ax, bx ;New digit temporarily in BX
mov cx, 10
mul cx ;Product is in DX:AX, but we won't use DX!
add bx ,ax ;Add new digit
jmp aggregate
return:
ret
您没有显示 16 位数字
将数字转换为文本的过程肯定需要使用字大小划分。
有关如何执行此操作的精彩解释,请参阅最近的 post Displaying numbers with DOS。它非常详细地解释了您需要了解的有关转换数字的所有信息。它甚至使用相同的技术在堆栈中压入一些值(你为此使用了 $ 字符)来知道数字在哪里结束。
ps。如果您觉得 the linked post 中的信息有用,请毫不犹豫地点赞它。 (当然也希望我的回答对你有用!)