Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 在装配中打印星形三角形_Assembly_X86_Masm_Irvine32 - Fatal编程技术网

Assembly 在装配中打印星形三角形

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

我想打印一个三角形,像这样:。 计算每行星星数的公式是: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 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) 试着从“变量”的角度来思考较低级别的“内存->地址->内容(字节)”,这种“变量”方式有时会限制你看到如何在字节/位级别操作数据的机会,从而以更简单的方式获得所需的结果。

我希望我能再做一次向上投票,只是为了评论“摒弃欧文风格,严格使用[]”