在装配中打印星形三角形

时间:2017-07-25 01:53:31

标签: assembly x86 masm irvine32

我正在尝试打印这样的三角形:in assembly。 找到每行中星数的公式为: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

我哪里错了?

1 个答案:

答案 0 :(得分:2)

虽然这不是完整的答案,但评论时间太长了,它应该会给你带来很大的帮助,因为:

http://kipirvine.com/asm/debug/index.htm

这基本上是你应该首先学习的东西(太宽泛+很长时间才能成为这个答案的一部分)。

在您知道如何使用调试器之后,您可以查看代码正在执行的操作,例如您将遇到的第一个问题之一:

mov ecx,numRows + 1没有做你认为它做的事情,你不能在汇编中使用数学表达式,你必须把它们写成单个指令。

只有一些指令允许使用某种非常严格且有限的数学表达式,例如mov用于寻址内存模式,这实际上是编译时得到的:mov ecx,[numRows + 1] =获取值来自+1地址。 numRows是DWORD,因此如果用户输入10,则内存如下所示(从numRows地址开始:0A 00 00 00 00 00 00 00 - 前4个字节由mov numRows,eax设置(哪个Irvine写的没有[]围绕内存引用,这是IMO非常糟糕的风格/品味)第5个字节位于count地址,由count DWORD 0行定义,因此4个归零字节。现在因此,mov ecx,[numRows + 1]将从内存中获取4个零,从0A字节后开始,并且#34;泄漏"一个字节到count

在编译时也允许使用数学表达式,即add eax,12+13*14正常,在组装期间产生单个常量。但是你应该阅读像this这样的文档来了解哪些参数组合是合法的,mov ecx,label + 1可以是立即恒定加载(在NASM中)="地址+ 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 instruction认为它正在计算内存地址,而它只会计算你的表达式:

lea  ecx,[eax+1]   ; ecx = value_numRows + 1

这很有效,即使eax + 1是非法地址进入内存,但是LEA不会尝试读取地址,它只会计算并存储到目标寄存器中。

......等等......这里的要点是:

1)学会调试你的代码(这对于进一步发展是绝对必要的)

2)放弃Irvine风格并严格使用[]围绕每个记忆取消引用,即围绕"变量",如果你写{{1},这可能会让你更快地抓住你的头。 (如果您知道哪些mov ecx,[numRows]+1个操作数是合法的,您应该觉得这看起来并不好看。)

3)尝试根据"变量"来改变你的想法。向较低级别"记忆 - >地址 - >内容(字节)","变量"方式有时会限制你看到机会如何在字节/位级操作数据,以更简单的方式获得所需的结果。