【问题标题】:Division by 8 with SHR instruction使用 SHR 指令除以 8
【发布时间】:2020-12-29 20:28:36
【问题描述】:

编写一个完整的汇编程序来读取 8 位数字,每个数字与键盘之间用一个空格分隔(使用单键输入功能)。将它们从字符转换为数字,计算平均分、最低分和最高分并显示在屏幕上。

提示:从每个字符中减去30h 以获得实际数字。在显示之前,将30h 添加到每个数字。对于除法运算,请使用适当的移位指令。

平均显示错误的答案!我哪里做错了?请帮助我理解 SRH 指令的划分。

Include emu8086.inc
.model small
.stack 100h  
.data

 
.code
 mov bh,0
 mov bl,9  
 mov ah,1
 mov dh,0
 mov cx,0    
 
 input:    
 int 21H   
 putc 20h
 sub al,30h
 inc cx
 add dh,al
 cmp al,bh
 JA _max
 cmp al,bl
 JB _min  
 cmp cx,8
 JB input
 
 
 print:
 mov ah,2 
 printn
 mov dl,bh 
 add dl,30h
 printn "Max: "
 int 21h
   
 printn
 mov dl,bl
 add dl,30h
 printn "Min: "
 int 21h 
 
 AND dh, 0FH
 
 mov Cl,3
 shr dh,cl
 
 or dh,30H
 
 printn
 mov dl,dh
 printn "Avg: "
 int 21h 
 
 exit:
 mov ah,4ch
 int 21h
 
 _max:
 mov bh,al 
 cmp al,bl
 JB _min  
 cmp cx,8
 jae print
 jb input
 
 _min:
 mov bl,al
 cmp cx,10
 jae print
 jb input

【问题讨论】:

  • 这是SHR 而不是SRH,但这在代码中很好。是的,你可以像这样除以 8。问题是你应该除以总和。此外,总和不应被屏蔽为 4 位。

标签: assembly dos x86-16 emu8086


【解决方案1】:

将无符号数除以 8 与将数字向右移动 3 次相同。在 8086 编程中,我们需要在执行shr 指令之前将移位计数放入CL 寄存器中。因为您已将总和(要除法)放在DH 寄存器中,并且您想显示来自DL 寄存器(由 DOS.PrintChar 函数请求)的平均值(除法结果),您可以只需 2 条指令即可:

mov cl, 11   ; 11 = 3 (is divide DH by 8) + 8 (is move DH to DL)
shr dx, cl

_min:
mov bl,al
cmp cx,10

就像 _max 一样,这个 _min 应该使用cmp cx, 8

更好的是,您可能不应该重复那么多代码!下面的代码使用相反的条件并将所有内容很好地结合在一起:

.code
  mov bx, 9    ; BH=0 is Max, BL=9 is Min
  xor dx, dx   ; DH=0 is Sum, DL=0 is Count
input:
  mov ah, 01h  ; DOS.GetCharacter
  int 21h  
  putc 20h
  sub al, 30h
  add dh, al   ; Add to Sum DH
  cmp al, bh
  jbe NotMax
  mov bh, al   ; Set new max BH
NotMax:
  cmp al, bl
  jae NotMin
  mov bl, al   ; Set new Min BL
NotMin:
  inc dx       ; Increment Count DL
  cmp dl, 8
  jb input

不要忘记在您的程序中添加一些有意义的 cmets,以便人们可以快速理解您所写的内容。

【讨论】:

  • @zx485:我一开始也是这么想的,但后来意识到这是故意移动 8 + 3 = 11 来模拟 mov dl,dh / shr dl,3。 (这在没有桶形移位器的 CPU 上会更快,所以每个计数都需要一个时钟。但是对于代码大小,这很好。是的,我知道不使用 CL 的 shr dl,3 需要 186 或更高版本。)
  • @PeterCordes:谢谢你的解释。我低估了优化代码的聪明之处。原谅我。
猜你喜欢
  • 2021-06-25
  • 1970-01-01
  • 2018-09-25
  • 1970-01-01
  • 2020-07-24
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多