【问题标题】:I want to print the even numbers first and then the odd numbers我想先打印偶数,然后再打印奇数
【发布时间】:2020-05-12 20:05:42
【问题描述】:
DOS segment
.model small
.stack 100h
.data
array1 dw 1,4,6,3,7   ; since division 8 bit divisor require 16 bit dividend
.code
 main proc
 mov ax,@data
 mov ds,ax
 lea si,array1   
 mov cx,5
 l1:   
 mov ax,[si] 
 mov bl,2
 div bl
 cmp ah,0
 jne odd           **if the remainder is not 0 means even**

 resume:   
 inc si   
 loop l1   

 odd:
 push ax                       **I am using stack**
 jmp resume

 mov cx,5
 l2:   
 mov ax,[si] 
 mov bl,2
 div bl
 cmp ah,0
 je even            **if the remainder is 0 means even**

 re:   
 inc si   
 loop l2   

 even:
 push ax
 jmp re

 mov cx,5
 l3:
 pop dx 
 mov ah,2
 int 21h
 loop l3
 main endp
end main

我相信我的算法是正确的,但我面临的问题是除法错误。我环顾四周,它发生在CX=0 时,但循环将如何工作?我很困惑。

如果有人告诉我解决方案,我将不胜感激

【问题讨论】:

  • 我指定了 mov cx,4 但为什么我的循环没有在 4 处停止
  • 你想用jmp resume做什么?因为看起来这会让你回到循环中。
  • 我不应该?我想我必须,因为当它跳转到标签时它会退出循环,所以我想也许我必须把它带回来进行下一次迭代
  • 我尝试在不使用 jmp 的情况下运行它,但如果我在无限期之前执行生命,则循环只迭代一次我该怎么办
  • 阅读代码。如果它只执行一次,它怎么会跳出循环呢?因为只有 1 个其他跳转指令 (je l2) 必须在它发生的地方。因此,如果在执行除法之后 ah=0,它将跳过循环指令,然后我们就走了。为什么 ah 可能为零?是时候使用调试器了。特别是,看看lea ax,[si] 会发生什么。

标签: assembly emu8086


【解决方案1】:

...如果余数不为0则表示偶数
...如果余数为 0 则表示偶数

不可能同时正确!

第一个循环压入奇数

lea si,array1   
mov cx,5
l1:   
mov ax,[si] 
mov bl,2
div bl
cmp ah,0
jne odd           **if the remainder is not 0 means even**
resume:   
inc si   
loop l1   
odd:
push ax                       **I am using stack**
jmp resume

问题在于您将 odd 标签放在了完成循环的 LOOP 指令的正下方(当 CX 变为 0 时)。代码将错误地落入这些 push axjmp resume 指令中!
你需要重新组织代码绕过push ax

cmp  ah, 0
je   Even
push ax     ; This pushes an ODD number BUT DOES IT ? (1)
Even:
inc  si     ; This advances to the next number BUT DOES IT ? (2)
loop l1

(1) AX 寄存器不再保存数组中的数字,因此您需要使用 push word ptr [si] 从数组中推送单词。
(2) 因为数组包含words,你需要使用add si, 2 前进2。

第二个循环压入偶数

mov cx,5
l2:   
mov ax,[si] 
mov bl,2
div bl
cmp ah,0
je even            **if the remainder is 0 means even**
re:   
inc si   
loop l2   
even:
push ax
jmp re

我对第一个循环所说的一切也适用于这里。此外,您需要使用lea si, array1 初始化SI 寄存器。

第三个循环打印所有被推送的内容

mov cx,5
l3:
pop dx 
mov ah,2
int 21h
loop l3

您从堆栈中弹出的是一个数字,但 DOS.Printchar 函数需要DL 中的一个字符。需要一点转换:

pop  dx
add  dl, '0'

您的程序中的一些问题源于您使用除以 2 来测试偶数/奇数。这使您将数组定义为单词,而您忘记更改 inc si 指令。
查看一个数字是偶数还是奇数的方法是查看它的最低位。您可以使用test 指令:

array1 DB 1, 4, 6, 3, 7
...
L1:
mov  al, [si]
test al, 1
jz   Even
push ax       ; Pushing the odd number still in the AL register
Even:
inc  si
dec  cx
jnz  L1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-07
    • 1970-01-01
    • 2011-08-26
    相关资源
    最近更新 更多