我必须用汇编语言做一个项目,我真的堆叠了。我想生成一个随机数(0-9)之后我选择并编号,直到找到数字。 我不需要那么复杂的事情
.MODEL SMALL
.STACK 100H
.DATA
m1 DB 'The number is bigger ','$'
m2 DB 'The number is smaller','$'
m3 DB 'You won','$'
m4 DB 'Choose the number ','$'
.CODE
MOV AX,@DATA
MOV DS,AX
MOV AH,09H
MOV DX,OFFSET m4
INT 21H
RANDGEN:
RANDSTART:
MOV AH, 00h
INT 1AH
MOV BH, 57
MOV AH, DL
CMP AH, BH
JA RANDSTART
MOV BH, 49
MOV AH, DL
CMP AH, BH
JB RANDSTART
mov ah, 2h
int 21h
E1:MOV AH,01H
INT 21H
CMP AL,DL
JG E2
CMP AL,DL
JL E3
MOV AH,09H
MOV DX,OFFSET m3
INT 21H
JMP E4
E2:MOV AH,09H
MOV DX,OFFSET m1
JMP E1
E3:MOV AH,09H
MOV DX,OFFSET m2
JMP E1
E4:MOV AH,4CH
INT 21H
END
答案 0 :(得分:1)
您必须学会如何使用某些调试器,并亲自了解您的代码所做的事情。
在找到一些调试器并学习如何使用它之前,停止在程序集中编程,没有必要继续,你只会浪费你的时间,甚至其他人,如果你会把每一个小问题带到堆栈溢出或其他论坛。
你应该使用那些"互联网"只有在你被困的时候才会出现问题。不了解特定的事情。这意味着您可以很好地描述一些短代码之前的CPU状态,执行它之后的状态,您期望的内容以及它与您的期望有何不同。然后人们可以解释为什么你的期望是错误的。
但是,如果您还将使用说明参考指南来验证您对特定说明的期望,那么您将能够在很短的时间内自行修复这些错误的90%。
你应该学习一些东西(并用新眼睛重新阅读你的来源,以便在你的代码中找到bug)。
CPU寄存器是"超级全局",无论谁将最后一个值写入寄存器,该值都在其中。如果你想保留一些值一段时间,要么确保寄存器不会被下一部分代码改变,要么将值存储在[stack]内存中的某个位置。或者将它(mov
)复制到某个寄存器中,如果你需要当前值的那个寄存器,则不会在下一部分代码中使用。
DL
,DH
和DX
都是CPU的相同寄存器,只是它的不同部分(位组)。 DX
= DH
* 256 + DL
,或者当您将其视为二进制数时,DL
低于DX
的8位,{{1}高8位。 DH
当然是8 + 8 = 16位。因此DX
中的第三位同时也是DH
的第11位,它的物理位置相同。
标志也只是寄存器(DX
)中的数值,仅受某些指令的影响。如果您将阅读关于F
(按条件代码跳转)指令系列的指令参考指南,您将学习那些不影响Jcc
(标志)的值,所以在这种情况下:
F
第二个CMP AL,DL
JG E2
CMP AL,DL
JL E3
将不会做任何新的事情,第一个已设置标志。寄存器中的值是存在的,直到它被某些指令改变为止,它不会消失"就这样"。通过在如此超短的代码中使用冗余指令,您可能会显示缺乏理解或浪费的方法(冗余指令会浪费CPU的周期,这在20世纪80年代是非常昂贵的事情,而在像这样的琐碎案例中它会给你带来很多皱眉和嘲弄...就像我在这里做的那样(皱眉部分肯定,不确定嘲弄,现在很难成为混蛋,因为人们现阶段已经在寻求建议通常情况下,早在20世纪80年代,这就像是因为没有掌握至少基础知识而被公开羞愧,但现在它应该是好的))。
最后关于你的随机生成器:
CMP
这又浪费了很多CPU周期,并且浪费了几条源代码行,总体来说它是不合理的神秘内容,所以源代码不易阅读和遵循。考虑这种相同的替代方式:
INT 1AH
MOV BH, 57
MOV AH, DL
CMP AH, BH
JA RANDSTART
MOV BH, 49
MOV AH, DL
CMP AH, BH
JB RANDSTART
这是相同的事情(加上修复返回0-9而不是1-9位数)。注意现在源"告诉"你的故事"与ASCII数字 INT 1AH
; cx:dx is 32 bit clock "time" in (1/18.21)s since boot
; I will use the least significant 8 bits of it (DL) as random ASCII digit
CMP DL, '9'
JA RANDSTART
CMP DL, '0' ; your original code compares with '1'!
JB RANDSTART
; so your original code will produce only 1-9 ASCII digits
比较,如果在上面,做新的随机。然后与ASCII数字'9'
进行比较,如下所示,做新的随机。" ,任何经验丰富的x86 ASM程序员都会读得非常流利并立即理解。
还有一件事就是"随机"发电机。 '0'
是8位寄存器,因此它可以具有从0到2 8 -1的值(当您将这8位作为无符号整数表示时)。但是,只有在DL
,10&#34;合法&#34;值'0' <= DL <= '9'
。如果时钟返回ASCII字符DL
(十进制为':'
),则大约需要14秒,直到58
将遍历所有DL
然后{{1值。那种非常慢的随机发生器(也不是很随机)。
要以天真的方式稍微改进一下,你可以这样做,例如:
58-255
如果你完全理解这些,并重新阅读你的来源,你应该能够找到你的所有错误。或者甚至更好,使用调试器亲眼看看,每个指令的作用,以及每个指令后的CPU状态会发生什么。
此外,如果您了解这些内容,您和其他读者的下一个来源将更具可读性,更短且更容易破译。当你向一些经验丰富的ASM程序员展示你当前的代码时,他们会继续说&#34;每个人都必须以某种方式学习它,它可以开始&#34; ,但另一个心灵的一部分也会大喊大叫&#34;杀死它,在产卵之前将其杀死。&#34; 通过做一些基本的重构,从像源码中删除基本废物,如复制品等等遵循语义的适当常量或0-47
别名:你会更容易阅读和回答你的问题(加上答案很可能只是重点,省略了大量无用的唠叨)。
由于您的代码不使用任何内存存储,因此只需查看寄存器视图和寄存器中的以下值,就可以非常轻松地遵循CPU状态的重要部分,这对您来说非常重要。代码(在较大的内存块中跟踪值有点繁琐,但当然可行,如果出现这种需要,调试器也允许您查看内存内容)。
如果我没有提及它,那么学习使用某些调试器绝对必要。