【问题标题】:Motorola 68000 Storage in Assembly摩托罗拉 68000 存储组装
【发布时间】:2017-11-17 06:15:37
【问题描述】:

编写此程序以使用四个标记获取空格分隔的用户输入,如果它们都是数字,则将标记加在一起,并将结果打印到终端。现在它适用于诸如“1 1 1 1”和“123 123 123 123”之类的数字,但是当我尝试添加 4 个七位数长的数字(7 位,因为这是极端情况)时,它只会添加最多 23068。这听起来像是我的一个标签或其他东西的尺寸问题,但我不确定。

代码如下:

*
        ORG     $0
        DC.L    $3000           * Stack pointer value after a reset
        DC.L    start           * Program counter value after a reset
        ORG     $3000           * Start at location 3000 Hex
*
*----------------------------------------------------------------------
*
#minclude /home/cs/faculty/cs237/bsvc/macros/iomacs.s
#minclude /home/cs/faculty/cs237/bsvc/macros/evtmacs.s
*
*----------------------------------------------------------------------
*
* Register use
*
*----------------------------------------------------------------------
*
start:  initIO                  * Initialize (required for I/O)
    setEVT          * Error handling routines
*   initF           * For floating point macros only    

                * Your code goes HERE
*Output info:               
    lineout header      *Display header info
    lineout prompt      *Display prompt
    linein  buffer      *Read input to buffer

    lea buffer,A1       *
    adda.l  D0,A1       *Add null terminator
    clr.b   (A1)        *

    lea buffer,A1       *Reload the beginning of buffer address

    move.l  #1,D1       *D1 is input counter and starts at 1

    clr.l   D2          *
    clr.l   D3          *Prepping registers for calculations
    move.l  #0,result   *

    move.l  A1,A2       *Duplicating address to use for strlen

top:    
    tst.b   (A1)        *Check for end of string
    BEQ rest            *If end, go to rest

    cmpi.b  #47,(A1)    *Check current byte against low end of ascii numbers
    BGT toprange        *This means byte *might* be an ascii number

    cmpi.b  #32,(A1)    *Byte is below range for numbers. Is it a space?
    BNE notno           *If this triggers, it's not a space and not a number. Exit.

    cmpi.b  #32,1(A1)   *Is the character after this a space? If yes, loop to top.
    BNE addit           *If not, it's either another valid byte or null terminator. 

    adda.l  #1,A1       *Increment token counter and loop to top.
    BRA     top 

toprange:   
    cmpi.b  #57,(A1)    *Is byte value higher than ascii numbers range?
    BGT notno           *If yes, it's not an ascii number. Exit. 

    cmpi.b  #32,1(A1)   *Is the byte after this a space?
    BEQ endoftoken      *If yes, that means this is the end of the token.

    tst.b   1(A1)       *If not, is this byte a null terminator?
    BEQ endoftoken      *If yes, this is the last token. Add it.

    adda.l  #1,A1       *Else increment the address pointer and loop.
    BRA top

endoftoken: 
    adda.l  #1,A1       *Increment pointer
    move.l  A1,D2       *
    sub.l   A2,D2       *Find length of token

    cvta2   (A2),D2     *Convert current token segment to number
    add.l   D0,result   *Add converted number to result address.
    BRA     top         *Loop to top.

addit:          
    tst.b   1(A1)       *Test for null
    BEQ endoftoken      *If null, go endof token to add it to running total

    addi.l  #1,D1       *If next byte isn't null, there might be more tokens. Incr & cont.
    adda.l  #1,A1   

    move.l  A1,A2       *Shift token starting point pointer forward
    BRA top 

rest:
    cmpi.l  #4,D1       *Check to make sure we have 4 tokens
    BNE incnums         *If not, exit on error

    move.l  result,D0   *Convert numbers back to text representations
    ext.l   D0
    cvt2a   result,#8
    stripp  result,#8
    lea result,A0
    adda.l  D0,A0
    clr.b   (A0)

    lea sum,A1          *Point to first bit of text for strcat
    lea output,A2       *Point to destination during copying
strcat1:
    tst.b   (A1)        *Null?
    BEQ strcat2         *Go to next segment of code
    move.b  (A1)+,(A2)+ *If not null, copy from A1 to A2. Post increment
    BRA strcat1

strcat2:
    move.b  #32,(A2)+   *Append space. Post increment
    lea result,A1       *Point to calculated result

strcat3:    
    tst.b   (A1)        *Is this byte null?
    BEQ printr          *If yes, go to print response.  
    move.b  (A1)+,(A2)+ *If not, copy byte to output string. 
    BRA strcat3

printr: 
    move.b  #46,(A2)+   *Append period to output string. 
    clr.b   (A2)        *Null terminate the string. 
    lineout output      *Print built string to terminal.
    BRA end 

incnums:
    lineout incno       *If here, there were not the correct number of tokens.
    BRA end


notno:
    cmpi.b  #1,D1       *This checks the token counter to determine which token was not a #
    BNE ch2
    lineout bn1
    BRA end

ch2:    
    cmpi.b  #2,D1
    BNE ch3
    lineout bn2
    BRA     end

ch3:    
    cmpi.b  #3,D1
    BNE ch4
    lineout bn3
    BRA end

ch4:    
    lineout bn4


end:



*Output result




        break                   * Terminate execution
*
*----------------------------------------------------------------------
*       Storage declarations

prompt: dc.b    'Enter the four space separated numbers:',0
sum:    dc.b    'The sum is',0
incno:  dc.b    'There are not four inputs.',0
buffer: ds.b    80
result: ds.l    3
output: ds.l    3
bn1:    dc.b    'The #1 input is not a number',0
bn2:    dc.b    'The #2 input is not a number',0
bn3:    dc.b    'The #3 input is not a number',0
bn4:    dc.b    'The #4 input is not a number',0
        end

编辑 1

看起来它与我将 ascii 表示形式转换为实际数字有关。我将.l 添加到结果标签。标签足够大,可以存储字符,但我没有向它移动足够大的块。

当我输入“9999999 9999999 9999999 9999999”并设置断点观看时,内存将正确显示26259FC的十六进制值,所以当我使用提供的宏将其转换回来时会出现问题。

我不希望任何人对此有解决方案,但也许有人有。

编辑2: 此代码已在 Sep Rowland 的指导下进行了修订(非常感谢)。我想我得到了他所涵盖的所有内容,并且已将修改后的代码作为答案提交。

【问题讨论】:

    标签: assembly motorola 68000


    【解决方案1】:

    错误(您已经发现)是ext.l D0。鉴于此指令对 D0 中的低位字进行符号扩展,因此结果为 off 也就不足为奇了。


    我很少有机会深入研究一些好的 68K 代码,所以我在这里介绍一些可以改进您的程序的 cmets。

    addi.l  #1,D1
    adda.l  #1,A1
    

    您可以编写这些从 #1 到 #8 的小添加,如果您使用 addq 指令会更优化:

    addq.l  #1,D1
    addq.l  #1,A1
    

    要在某个输入不是数字时显示错误消息,如果将D1(1-4)中的数字转换为字符(“1”-“4”)并写入,则可以更简单地编写在单个错误消息中:

    lea     bn,A1
    addi.b  #48,D1   *From number to character
    move.b  D1,5(A1) *Replaces the dot in the error message
    lineout bn
    
    ...
    
    bn:     dc.b    'The #. input is not a number',0
    

    output: ds.l    3
    

    这个 输出 缓冲区不够长,无法满足您正在做的事情!
    您只有 12 个字节,但您首先复制 10 个字符长的 sum 消息,添加一个空格,添加几个字符长的结果,添加一个句点并添加一个零。显然是缓冲区溢出。
    现在您可以使这个缓冲区更长,或者智能地停止复制周围的所有内容,只需将 result 缓冲区放置在 sum 消息旁边(附加一个空格并且没有终止零) .然后一次性显示组合的 sumresult 文本。一个更简单的解决方案。

    move.l  result,D0   *Convert numbers back to text representations
    cvt2a   result,#8
    stripp  result,#8
    lea     result,A2
    adda.l  D0,A2
    move.b  #46,(A2)+   *Append period to output string. 
    clr.b   (A2)        *Null terminate the string. 
    lineout sum         *Print built string to terminal.
    BRA end 
    
    ...
    sum:    dc.b    'The sum is '
    result: ds.l    3
    

    cmpi.b  #32,1(A1)   *Is the character after this a space? If yes, loop to top.
    BNE     addit       *If not, it's either another valid byte or null terminator. 
    
    adda.l  #1,A1       *Increment token counter and loop to top.
    BRA     top 
    
    toprange:
    

    在这里您可以在代码中创建一个快捷方式,从而加快程序运行速度。
    无需BRA 一直到顶部,您将在那里进行 3 次不必要的测试。

    SkipWhitespace:
        cmpi.b  #32,1(A1)
        BNE     addit
        addq.l  #1,A1
        BRA     SkipWhitespace
    toprange:   
    

        move.l  A1,A2       *Duplicating address to use for strlen
    top:    
    
        ...
    
        move.l  A1,A2       *Shift token starting point pointer forward
        BRA     top
    rest:
    

    始终尝试编写多余的指令。

    topEx:
        move.l  A1,A2       *Duplicating address to use for strlen
    top:    
    
        ...
    
        BRA     topEx
    rest:
    

    【讨论】:

    • 说真的,感谢您对此进行了如此详细的介绍。我将与我的代码一起审查它以进​​行改进。尽管这是组装,但在如此低的水平上进行优化的能力对我来说仍然非常有价值。 While(1) { 谢谢 }
    • 根据您的指导修改了我提供的答案。我想我得到了一切。我很高兴我能够回去进行我认为应该首先进行的更正,但这种体验将持续到下一个编写的程序中。再次感谢!
    【解决方案2】:

    最初的问题: ext.l 指令。 Sep Rowland 在提供的其他答案之一中对此进行了解释。

    其他修订: 在Sep的指导下,我对代码进行了多方面的优化。

    +1 用于内存查看器和断点。

    * Problem statement: Read input and determine if 4 numbers are provided. Add numbers.
    * Input: ### ### ### ###
    * Output: "The sum is ###"
    * Error conditions tested: Correct number of data provided. Number vs Char
    *  Also handles leading white spaces/multiple spaces between tokens
    * Included files: None
    * Method and/or pseudocode: 
    * References: 
    *----------------------------------------------------------------------
    *
            ORG     $0
            DC.L    $3000           * Stack pointer value after a reset
            DC.L    start           * Program counter value after a reset
            ORG     $3000           * Start at location 3000 Hex
    *
    *----------------------------------------------------------------------
    *
    #minclude /home/cs/faculty/cs237/bsvc/macros/iomacs.s
    #minclude /home/cs/faculty/cs237/bsvc/macros/evtmacs.s
    *
    *----------------------------------------------------------------------
    *
    * Register use
    *
    *----------------------------------------------------------------------
    *
    start:  initIO                  * Initialize (required for I/O)
        setEVT          * Error handling routines
    *   initF           * For floating point macros only    
    
    
        lineout header      *Display header info
        lineout prompt      *Display prompt
        linein  buffer      *Read input to buffer
        lea buffer,A1       *
        adda.l  D0,A1       *Add null terminator
        clr.b   (A1)        *   
        lea buffer,A1       *Reload the beginning of buffer address
        clr.l   D1          *D1 is input counter and starts at 0
        clr.l   D2          *D2 used as workspace
        move.l  #0,result   *Clearing garbage out of memory address
        move.l  A1,A2       *A2 used for strlen
    
    top:    
        tst.b   (A1)        *Check for end of string
        BEQ rest            *If end, go to rest
    
        cmpi.b  #47,(A1)    *Check current byte against low end of ascii numbers
        BGT checktoprange   *This means byte *might* be an ascii number
    
        cmpi.b  #32,(A1)
        BNE notnumber
    
    whitespace:             *This will eat whitespace anywhere in buffer
        addq.l  #1,A1       *If we are here, we know current location is space
        cmpi.b  #32,(A1)    *So increment pointer and check for additional spaces
        BEQ whitespace
        move.l  A1,A2       *If we are here, we encountered a token
        BRA top             *Shift our pointer for token start location
    
    
    checktoprange:  
        cmpi.b  #57,(A1)    *Is byte value higher than ascii numbers range?
        BGT notnumber       *If yes, it's not an ascii number. Exit. 
    
        cmpi.b  #32,1(A1)   *Is the byte after this a space?
        BEQ endoftoken      *If yes, that means this is the end of the token.
    
        tst.b   1(A1)       *If not, is this byte a null terminator?
        BEQ endoftoken      *If yes, this is the last token. Add it.
    
        addq.l  #1,A1       *Else increment the address pointer and loop.
        BRA top
    
    endoftoken: 
        addq.l  #1,A1       *Increment pointer
        move.l  A1,D2       *
        sub.l   A2,D2       *Find length of token
    
        cvta2   (A2),D2     *Convert current token segment to number
    
        add.l   D0,result   *Add converted number to result address.
        addq.l  #1,D1       *Increment token counter
        BRA     top         
    
    rest:
        cmpi.l  #4,D1       *Check to make sure we have 4 tokens
        BNE incnums         *If not, exit on error
    
        move.l  result,D0   *Convert numbers back to text representations
        cvt2a   result,#8
        stripp  result,#8
        lea result,A0
        adda.l  D0,A0
        move.b  #46,(A0)+
        clr.b   (A0)
        lineout sum
        BRA end
    
    
    incnums:
        lineout incno       *If here, there were not the correct number of tokens.
        BRA end
    
    
    notnumber:
        lea bn,A1
        addi.b  #49,D1       *From number to character
        move.b  D1,5(A1)     *Replaces the dot in the error message
        lineout bn
    
    end:    
    
            break                   * Terminate execution
    *
    *----------------------------------------------------------------------
    *       Storage declarations
    
    header: dc.b    'This is a header',0
    prompt: dc.b    'Enter the four space separated numbers:',0
    incno:  dc.b    'There are not four inputs.',0
    buffer: ds.b    80
    bn:     dc.b    'The #. input is not a number',0
    sum:    dc.b    'The sum is '
    result: ds.l    1
    
    
            end
    

    【讨论】:

    • 我看到您巧妙地将result 放置在存储区域的最后一项。对于您的程序的主循环,它只引用一个 dword 很好,但要转换为文本表示,您将需要更多(大约 10 个字节左右) .最好明确声明您的程序将使用的内存,而不是进入任何碰巧在您的程序之外空闲的内存。
    • 我将继续观察程序运行时的内存,以帮助了解边缘情况以及它将需要多少内存。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多