Assembly 组装8086。从标准输入中读取数个数字,以2为基数。在屏幕上以10为基数打印这些数字
所以,我必须把以2为基数的数字转换成以10为基数的数字,我不知道该怎么做。这就是我的程序现在的样子,但我不确定我现在得到的是否能正常工作。转换部分真的让我很为难,但可以肯定的是,我的代码中有很多错误,所以任何帮助都将不胜感激Assembly 组装8086。从标准输入中读取数个数字,以2为基数。在屏幕上以10为基数打印这些数字,assembly,x86-16,Assembly,X86 16,所以,我必须把以2为基数的数字转换成以10为基数的数字,我不知道该怎么做。这就是我的程序现在的样子,但我不确定我现在得到的是否能正常工作。转换部分真的让我很为难,但可以肯定的是,我的代码中有很多错误,所以任何帮助都将不胜感激 assume cs:code, ds:data data segment msg db 'Give numbers:$' numbers LABEL BYTE max_size DB 100 numbers_len DB ? number D
assume cs:code, ds:data
data segment
msg db 'Give numbers:$'
numbers LABEL BYTE
max_size DB 100
numbers_len DB ?
number DB 100 dup (?)
ten db 10
errm db 'Numbers not in binary.$'
data ends
code segment
start:
mov ax,data
mov ds,ax
mov ah,09h
mov dx,offset msg
int 21h
mov AH,0Ah
mov DX,offset numbers
int 21h
mov CL,numbers_len
mov CH,0
mov SI,0
repeat:
mov AL,number[SI]
cmp AL,' '
je conversion
check:
cmp AL,'0'
jb erro
cmp AL,'1'
ja erro
jmp conversion
continue:
inc SI
dec cx
jcxz print
jmp repeat
conversion:
jmp continue
print:
pop dx
add dl,'0'
mov ah,02h
int 21h
loop print
erro:
mov ah,09h
mov dx,offset errm
int 21h
mov ax,4c00h
int 21h
code ends
end start
首先,不可能直接执行从base-2到base-10的转换:必须将base-2表示转换为寄存器中的实际值,然后将其转换为base-10。这是因为这些基数彼此不相关,例如,无法通过对2应用整数幂来获得10 下面是从基数为2的字符串转换为数字的代码。不执行错误检查,每个不是
1
的字符都被简单地视为0
; input : bx - the starting address of the string, cx - its length
; output : ax - contents of the string interpreted as base-2
from_bin:
mov di, bx
add di, cx
sub di, 1
xor ax, ax
mov dx, 1
.loop:
cmp di, bx
jb .end
cmp byte [di], '1'
jne .loop_next
add ax, dx
.loop_next:
shl dx, 1
sub di, 1
jmp .loop
.end:
ret
如您所见,如果当前位置存在1
,则代码通过向其添加dx
来建立ax
中的返回值dx
对应于循环每次迭代中的2^n值,其中n
是字符串中的当前位置,从零开始
将值转换为base-10的代码使用除法将存储在寄存器中的“本机”base-2值转换为该值的连续base-10位数
; input : ax - the number to convert
; di - the last writable address of the output buffer
; output : di - the address of the last written character
; destroys bx, cx, dx
to_dec:
mov cx, 10
.loop:
xor dx, dx
div cx
mov bx, dx
or bl, '0'
mov [di], bl
test ax, ax
jz .end
sub di, 1
jmp to_dec
.end:
ret
转换是“向后”进行的:它从最低的位置开始,并一直向上,只要除法的结果不是零——这意味着还有更多的东西要转换。这也是函数需要获取缓冲区的最后一个可写地址而不是其开头的原因。好的,您遇到了什么问题?您已经大致说明了所需的行为和输出,但是您没有提到所提供的输入,也没有提到所观察到的输出。求求你,求求你-不要说“它不工作了”。您是否已使用调试器逐步完成了代码?具体来说,您需要帮助的是什么?在我给出数字后,它进入了一个无限循环TurboDebugger始终是DOS的一个好调试器。无论如何,请查看
检查:
标签后面的代码。如果数字太小,请勾掉。如果数字太大,请勾掉。如果数字正好(0或1),则jmp转换为。在这一点上,如果您从未使用jmp进行转换,那么您就可以直接返回到您应该到达的位置。
Hmmmmm?!您的另一个问题是,您的循环计数器,CX
在int21h
期间未被触动-它不是,您应该先推它,然后再弹出它。接下来,在循环中弹出dx
。它被推过这么多次吗?@enhzflep我看到int 21h/02h 21h/09h和21h/0ah。哪一个破坏CX、CL或CH?“据我所知,这些特殊的中断并没有破坏CX。”迈克尔·佩奇——的确如此。进一步检查发现,我没有正确地记住这一点:垂下头去用ECC搜索神经元:addax,1
将保存一个寄存器;在循环之前使用mov-dx,1
对我来说似乎是混淆。(如果您希望使用较小的代码大小来避免立即生效,请使用inc ax
)。哦,我看到你是从LSB(字符串的结尾)而不是开始循环的。您可以shl ax,1
在正在累积的数字的底部打开一个新的空格。此外,cmp dl,[di]
(dl中有'0')/adc ax,ax
将在1
位(从'0'-'1'产生借位)或0
位(从它们相等的位置)中移动,因此您可以避免单独的shl ax,1