Assembly 在装配中打印星形三角形
我想打印一个三角形,像这样:。 计算每行星星数的公式是:2*x+1。 这是到目前为止我的代码。我似乎在无限循环Assembly 在装配中打印星形三角形,assembly,x86,masm,irvine32,Assembly,X86,Masm,Irvine32,我想打印一个三角形,像这样:。 计算每行星星数的公式是:2*x+1。 这是到目前为止我的代码。我似乎在无限循环 .data prompt BYTE "Please enter the number of rows in the pyramid: ", 0 numRows DWORD ? count DWORD 0 .code main PROC mov edx, OFFSET prompt call WriteString call ReadInt mov n
.data
prompt BYTE "Please enter the number of rows in the pyramid: ", 0
numRows DWORD ?
count DWORD 0
.code
main PROC
mov edx, OFFSET prompt
call WriteString
call ReadInt
mov numRows,eax
mov ecx,numRows + 1 ; Let ecx = numRows + 1
L1:
inc count ; Increment count
mov eax,ecx
L2:
sub eax,count ; eax = eax - count
mov al, ' ' ; Print spaces
call WriteChar
loop L2
L3:
mov ebx,count ; ebx = count
add ebx,count ; ebx = ebx + count
sub ebx,1 ; 2x - 1
mov al, '*' ; Printing the star pattern
call WriteChar
loop L3
call CrLf
loop L1
exit
main ENDP
END main
我错在哪里?虽然这不是完整的答案,但它太长了,无法发表评论,应该对您有很大帮助,因为: 这基本上是你应该首先学习的东西(而且太宽+太长,不能成为这个答案的一部分)
了解如何使用调试器后,您可以查看代码正在执行的操作,例如,您将遇到的第一个问题之一:
mov-ecx,numRows+1
不能做你认为它能做的事,你不能在汇编中使用数学表达式,你必须把它们作为单个指令来编写
只有一些指令允许某种非常严格和有限的数学表达式,比如mov
用于寻址内存模式,这实际上是编译时得到的:mov ecx,[numRows+1]
=从+1地址获取值numRows
是DWORD,因此如果用户输入了10,内存看起来是这样的(从numRows
地址开始:0A 00 00
-前4个字节是由mov numRows,eax
设置的(Irvine在编写内存引用时没有[]
,这是我非常糟糕的风格/品味)第5个字节位于count
地址,该地址由count DWORD 0
行定义,因此为4个零字节。现在mov ecx,[numRows+1]
将从内存中提取4个零,从0A
字节之后开始,并将一个字节“泄漏”到count
在编译时也允许使用数学表达式,例如,addeax,12+13*14
可以,在汇编过程中生成单个常量。但是您应该通读文档,了解哪些参数组合是合法的,mov ecx,label+1
可以是立即常量加载(在NASM中)=“address+1”,或MASM中的内存加载(来自地址+1的值),也不执行“值+1”
要做你想做的事,你需要:
mov ecx,[numRows] ; load the VALUE numRows back into ecx
inc ecx ; ecx = numRows+1
但由于eax已经包含numRows
值,您可以避免获取内存,因此在这种特殊情况下,这就足够了:
mov ecx,eax ; copy the numRows value from eax into ecx
inc ecx ; ecx = numRows+1
但是,由于此数学表达式非常简单,足以适应一种可能的寻址模式,因此您可以利用它来认为它正在计算内存地址,而它将只计算您的表达式:
lea ecx,[eax+1] ; ecx = value_numRows + 1
这是可行的,即使eax+1是内存中的非法地址,但LEA
不会尝试读取地址,它只会计算地址并存储到目标寄存器中
…等等…这里的要点是:
1) 学会调试您的代码(这对于进一步开发非常重要)
2) 抛弃Irvine风格,严格使用[]
来处理每一个内存解引用,即围绕“变量”,如果您编写mov ecx,[numRows]+1
(如果您知道哪个mov
操作数是合法的,您应该会觉得这看起来不太好)
3) 试着从“变量”的角度来思考较低级别的“内存->地址->内容(字节)”,这种“变量”方式有时会限制你看到如何在字节/位级别操作数据的机会,从而以更简单的方式获得所需的结果。我希望我能再做一次向上投票,只是为了评论“摒弃欧文风格,严格使用[]”