我试图让这段代码工作,但是我一直在转换中遇到问题,我尝试了一些示例,这些示例是类似问题的答案,但是没有一个可以工作,但是从中我修补了一下我认为代码的版本,但它仍然无效。
org 100h
jmp calc
m1 db 0dh, 0ah, "Input width. $"
m2 db 0dh, 0ah, "Input perimeter. $"
m3 db 0dh, 0ah, "width= $"
m4 db 0dh, 0ah, "height= $"
width dw 8,0, 8 dup(0)
height dw 8,0, 8 dup(0)
w dw 0
h dw 0
calc:
mov dx, offset m1
mov ah, 9 ;output message
int 21h
mov dx, offset width
mov ah, 0ah ;read input for width
int 21h
mov si, offset width+2
xor bx, bx
.next_digit1:
xor ax, ax
mov al, byte ptr [si]
inc si
cmp al, '0'
jb .done1
cmp al, '9'
ja .done1
sub al, '0'
imul bx, 10 ;convert width string into a number
add bx, ax
jmp .next_digit1
.done1:
mov ax, bx
mov w, ax
mov dx, offset m3
mov ah, 9 ;output message
int 21h
mov ah, 2 ;output the result
int 21h
mov ah, 0ah ;read input for width
int 21h
mov dx, offset m2
mov ah, 9 ;output message
int 21h
mov dx, offset height
mov ah, 0ah ;read input for width
int 21h
mov si, offset height+2
xor bx, bx
.next_digit2:
xor ax, ax
mov al, byte ptr [si]
inc si
cmp al, '0'
jb .done2
cmp cx, '9'
ja .done2
sub al, '0'
imul bx, 10 ;convert width string into a number
add bx, ax
loop .next_digit2
.done2:
shr ax, 2
sub ax, w
mov h, ax
mov dx, offset m4
mov ah, 9 ;output message
int 21h
mov ah, 2 ;output the result
int 21h
我有两个问题。
我显然是在为周边分区做错了,因为它给出了这个错误:
划分错误 - 溢出。 手动处理此错误, 在中断向量表中更改INT 0的地址。
即使看起来它现在应该可以工作,但在所有处理之后,w和h似乎仍然等于0,即使它们应该等于用户输入的值。
答案 0 :(得分:1)
Lemme对此表示不满......未经测试!
org 100h
jmp calc
m1 db 0dh, 0ah, "Input width. $"
m2 db 0dh, 0ah, "Input perimeter. $"
m3 db 0dh, 0ah, "width= $"
m4 db 0dh, 0ah, "height= $"
width dw 8,0, 8 dup(0)
height dw 8,0, 8 dup(0)
w dw 0
h dw 0
calc:
mov dx, offset m1
mov ah, 9 ;output message
int 21h
mov dx, offset width
mov ah, 0ah ;read input for width
int 21h
mov si, offset width+2
xor bx, bx
.next_digit1:
xor ax, ax
mov al, byte ptr [si]
inc si
cmp al, '0'
jb .done1
cmp al, '9'
ja .done1
sub al, '0'
imul bx, 10 ;convert width string into a number
add bx, ax
jmp .next_digit1
.done1:
mov ax, bx
mov w, ax
mov dx, offset m3
mov ah, 9 ;output message
int 21h
; I think you're good to here
; this is meaningless - what's in dl?
mov ah, 2 ;output the result
int 21h
; better load dx here, eh?
mov ah, 0ah ;read input for width
int 21h
; in fact, don't do it here
mov dx, offset m2
mov ah, 9 ;output message
int 21h
mov dx, offset height
mov ah, 0ah ;read input for width
; comment is wrong - no matter
int 21h
mov si, offset height+2
xor bx, bx
.next_digit2:
xor ax, ax
mov al, byte ptr [si]
inc si
cmp al, '0'
jb .done2
cmp cx, '9'
ja .done2
sub al, '0'
imul bx, 10 ;convert width string into a number
add bx, ax
loop .next_digit2
.done2:
shr ax, 2
sub ax, w
mov h, ax
mov dx, offset m4
mov ah, 9 ;output message
int 21h
; again, not what you want
mov ah, 2 ;output the result
int 21h
我认为你已经将“转换字符串转换为数字”部分非常正确。现在,要输出结果,您必须“将数字转换为字符串”。你可能想要为字符串声明一个缓冲区,尽管一次可以打印一个字符。我们希望将数字重复除以10 - 记住div
使用dx:ax
。在div
之后,商位于ax
,余数位于dx
。这是我们感兴趣的其余部分。不幸的是,我们将剩余部分“放在最右边”,我们希望首先打印“em”。有几种方法可以解决这个问题。最简单的可能是从缓冲区的“结束”(最右端)开始并“向后”工作。您可能希望使用'$'预先填充缓冲区,以便可以使用int 21h/9
进行打印。一个16位数字最多可以使用五位数 - 你需要一个额外的'$'。从最后一个'$'开始,当你得到一个余数(它将在0到9之间,所以只在dl
中)为它添加'0'(48或30h),并将其放入缓冲。如果商为零,我们就完成了。如果不是,则将索引递减(!)到缓冲区中并再次执行。当你完成后,你(可能)不会在缓冲区的开头,所以将你的索引转移到缓冲区到dx打印它。
另一种方法是将push
每个剩余部分放到堆栈上 - 计算它 - 并按正确顺序关闭它们pop
以一次打印一个。在之前或之后添加'0'。我喜欢这样的int 29h
- 打印al
没有副作用,但我不确定我们是否“应该”使用它。记录为“供内部使用”,我理解,但效果很好。 :)
除非我弄错了,emu8086包含一个调试器,这应该是一个很好的帮助!拉尔夫布朗的中断名单也将帮助你。在线版本是好的,但如果你下载整个混乱并“安装”它,有“奖金功能”(ports.lst.memory.lst等)。如果你正在做DOS(浪费时间,可以说),拉尔夫是你最好的朋友!兰迪海德的旧16位“装配艺术”也很好。 32位版本使用HLA语法,这是“完全不同”。我认为,16位版本应该与emu8086语法“非常接近”。
勇气!
答案 1 :(得分:0)
划分错误 - 溢出。要手动处理此错误,请在中断向量表中更改INT 0的地址。
表示除以零。您应该调试代码并检查实际处理的值。
此外:
mov ax, bx
mov bx, 2
div bx
注意div
提供16位除数uses the pair DX:AX
as dividend时。您似乎只划分AX
的值,但不要将DX
初始化为零。当除以2(或任何2的幂)时,使用右移也不是更容易(也更有效):
shr ax, 2 // performs a bitwise shift right, effectively dividing AX by two
即使看起来它现在应该可以工作,但在所有处理之后,w和h似乎仍然等于0,即使它们应该等于用户输入的值。
请查看function 0Ah of interrupt 21h的文档,因为它要求缓冲区采用特定格式:
因此,如果你有一个8字节的缓冲区(8个字符),那么声明应如下所示:
# first byte = capacity of 8 characters;
# second byte = zero to indicate the buffer is initially empty; this will receive the actual size of input read
# remaining eight bytes = the actual buffer, initialized to binary zeros (could be dup(?) as well)
buffer db 8, 0, 8 dup(0)