无法理解为什么程序集不起作用,即使从值寄存器正确复制了值,输出也没有显示正确的结果

问题描述 投票:0回答:1

我正在尝试在 emu8086 中构建一个程序,该程序将作为输入 1 8 位二进制数给出,然后在输出中显示它的十六进制形式。

我的代码是这样的:

data segment

ends

stack segment
    dw   128  dup(0)
ends

code segment
start:



mov ax,data
mov ds,ax
mov cx,0
mov bl,8

input:

mov ah,07h
int 21h

cmp al,46

sub al,30h
cmp al,0

je valid

cmp al,1

je valid

jmp input

valid:

cmp bl,0

je exit

sub bl,1

shl cl,1

add cl,al

jmp input

exit:


mov bl,15

and bl,cl

cmp bl,0

je printzero

cmp bl,1

je printone

cmp bl,2


je printtwo


cmp bl,3


je printthree


cmp bl,4


je printfour


cmp bl,5


je printfive


cmp bl,6


je printsix


cmp bl,7



je printseven


cmp bl,8


je printeight



cmp bl,9



je printnine


cmp bl,10


je printa



cmp bl,11


je printb


cmp bl,12


je printc


cmp bl,13


je printd


cmp bl,14


je printe


cmp bl,15


je printf


printzero:

mov dl,'0'

mov ah,02h

int 21h

jmp exit2



printone:


mov dl,'1'

mov ah,02h

int 21h

jmp exit2


printtwo:

mov dl,'2'

mov ah,02h

int 21h

jmp exit2



printthree:

mov dl,'3'


mov ah,02h

int 21h

jmp exit2



printfour:  

mov dl,'4'


mov ah,02h

int 21h

jmp exit2



printfive:

mov dl,'5'

mov ah,02h

int 21h

jmp exit2




printsix:


mov dl,'6'

mov ah,02h

int 21h

jmp exit2



printseven:

mov dl,'7'

mov ah,02h

int 21h

jmp exit2




printeight:

mov dl,'8'

mov ah,02h

int 21h

jmp exit2



printnine:

mov dl,'9'

mov ah,02h

int 21h

jmp exit2

printa:


mov dl,'A'

mov ah,02h

int 21h

jmp exit2



printb:

mov dl,'B'

mov ah,02h

int 21h

jmp exit2



printc:

mov dl,'C'

mov ah,02h

int 21h

jmp exit2



printd:

mov dl,'D'

mov ah,02h

int 21h

jmp exit2



printe:

mov dl,'E'

mov ah,02h

int 21h

jmp exit2


printf:

mov dl,'F'


mov ah,02h

int 21h

jmp exit2


exit2:  

mov bl,240

and bl,cl

cmp bl,0

je printzero2

cmp bl,1

je printone2

cmp bl,2


je printtwo2


cmp bl,3


je printthree2


cmp bl,4


je printfour2


cmp bl,5


je printfive2


cmp bl,6


je printsix2


cmp bl,7



je printseven2


cmp bl,8


je printeight2



cmp bl,9



je printnine2


cmp bl,10


je printa2



cmp bl,11


je printb2


cmp bl,12


je printc2


cmp bl,13


je printd2


cmp bl,14


je printe2


cmp bl,15


je printf2




printzero2:

mov dl,'0'

mov ah,02h

int 21h

jmp exit3



printone2:


mov dl,'1'

mov ah,02h

int 21h

jmp exit3


printtwo2:

mov dl,'2'

mov ah,02h

int 21h

jmp exit3



printthree2:

mov dl,'3'


mov ah,02h

int 21h

jmp exit3



printfour2:  

mov dl,'4'


mov ah,02h

int 21h

jmp exit3



printfive2:

mov dl,'5'

mov ah,02h

int 21h

jmp exit3




printsix2:


mov dl,'6'

mov ah,02h

int 21h

jmp exit3



printseven2:

mov dl,'7'

mov ah,02h

int 21h

jmp exit3




printeight2:

mov dl,'8'

mov ah,02h

int 21h

jmp exit3



printnine2:

mov dl,'9'

mov ah,02h

int 21h

jmp exit3

printa2:


mov dl,'A'

mov ah,02h

int 21h

jmp exit3



printb2:

mov dl,'B'

mov ah,02h

int 21h

jmp exit3



printc2:

mov dl,'C'

mov ah,02h

int 21h

jmp exit3



printd2:

mov dl,'D'

mov ah,02h

int 21h

jmp exit3



printe2:

mov dl,'E'

mov ah,02h

int 21h

jmp exit3


printf2:

mov dl,'F'


mov ah,02h

int 21h

jmp exit3 


exit3:




mov ax, 4c00h
int 21h  

ends

end start

我很快意识到你不需要将每个输入存储在数组中,你可以将存储数字的寄存器的值左移 1,然后添加输入(1 或 0)。我希望我的代码能够工作,但是我遇到一个问题:

存储我的号码值的寄存器是

CL
。如果我按此顺序键入
11110000
,则它会正确运行,
CL
的值将变为
F0
,这就是我想要的。我将其通过AND
Fh
的掩码来提取4个LSB,然后通过
F0h
的AND掩码来提取4个MSB,但是在输出中我得到了
00
。老实说,我不知道我错在哪里。
BL
的值寄存器与
CL
寄存器的值相同,但仍然不起作用。

assembly x86-16 emu8086 bitmask
1个回答
0
投票

必要的更正

  mov bl,8
input:
  mov ah,07h
  int 21h
  cmp al,46
  sub al,30h
  cmp al,0
  je  valid
  cmp al,1
  je  valid
  jmp input
valid:
  cmp bl,0
  je  exit
  sub bl,1
  shl cl,1
  add cl,al
  jmp input
exit:
  • cmp al,46
    指令没有任何作用。这是之前编辑留下的内容:只需将其删除即可。
  • 输入循环运行 1 次太多了!幸运的是,您没有将第九个输入添加到 CL 寄存器。原因是您在错误的位置检查 BL 是否变为 0。见下文。

您可以简化检查以及循环:

  mov  bl, 8
input:
  mov  ah, 07h   ; DOS.DirectSTDINInput
  int  21h       ; -> AL
  sub  al, 30h   ; Convert from character to number [0,9]
  cmp  al, 1     ; Everything other than [0,1] is ABOVE 1 ...
  ja   input     ; and so `JA input` will go repeat the input
  shl  cl, 1     ; Make room in CL
  add  cl, al    ; Add the new digit
  dec  bl        ; `DEC` already sets the flags
  jnz  input     ; Repeating 8 times means we jump back 7 times
exit:

exit:
  mov bl,15
  and bl,cl
  cmp bl,0
  je  printzero
  cmp bl,1
  je  printone

  ...

exit2:  
  mov bl,240
  and bl,cl
  cmp bl,0
  je  printzero2
  cmp bl,1
  je  printone2

  ...
  • 您需要先显示最高有效数字!因此,在 exit 使用掩码 240 检索高半字节,在 exit2 使用掩码 15 检索低半字节。
  • 你并没有真正取回高半字节! 240 的
    and
    的作用是从 BL 寄存器中删除低半字节,但高半字节仍然保留在原来的位置。这意味着 BL 中的值位于 {0,16,32,48,64,80,96,112,128,144,160,176,192,208,224,240} 中。

快速修复就是替换一系列

cmp bl,?
指令:

exit:
  mov  bl, 240
  and  bl, cl
  cmp  bl, 0
  je   printzero2
  cmp  bl, 16
  je   printone2
  cmp  bl, 32
  je   printtwo2
  ...

exit2:
  mov  bl, 15
  and  bl, cl
  cmp  bl, 0
  je   printzero
  cmp  bl, 1
  je   printone
  cmp  bl, 2
  je   printtwo
  ...

改进的第一步

目前您的程序包含大量重复指令。存在更好的解决方案,我确信 @PeterCordes 提供的链接将揭示这些。
尽管如此,除了我自己完成整个任务之外,我建议您研究下面的代码,您自己会发现这已经大大简化了程序,并且它演示了如何编写可读的代码。请注意,我不会将其视为“最佳”解决方案: mov bl, 8 input: mov ah, 07h ; DOS.DirectSTDINInput int 21h ; -> AL sub al, 30h ; Convert from character to number [0,9] cmp al, 1 ; Everything other than [0,1] is ABOVE 1 ... ja input ; and so `JA input` will go repeat the input shl cl, 1 ; Make room in CL add cl, al ; Add the new digit dec bl ; `DEC` already sets the flags jnz input ; Repeating 8 times means we jump back 7 times ; --------------- mov bl, 240 ; High Nibble mask and bl, cl ; BL = {0, 16, 32, 48, ... , 208, 224, 240} mov dl, '0' cmp bl, 0 je printHigh mov dl, '1' cmp bl, 16 je printHigh ... mov dl, 'E' cmp bl, 224 je printHigh mov dl, 'F' ; No need for `CMP BL, 240`. It's 240 for sure printHigh: mov ah, 02h int 21h ; --------------- mov bl, 15 ; Low Nibble mask and bl, cl ; BL = {0, 1, 2, 3, ... , 13, 14, 15} mov dl, '0' cmp bl, 0 je printLow mov dl, '1' cmp bl, 1 je printLow ... mov dl, 'E' cmp bl, 14 je printLow mov dl, 'F' ; No need for `CMP BL, 15`. It's 15 for sure printLow: mov ah, 02h int 21h ; --------------- mov ax, 4C00h int 21h

© www.soinside.com 2019 - 2024. All rights reserved.