组装中的摩托罗拉 68000 存储
Motorola 68000 Storage in Assembly
编写此程序是为了接受 space 带四个标记的定界用户输入,如果它们都是数字,则将这些标记加在一起,并将结果打印到终端。现在它适用于诸如“1 1 1 1”和“123 123 123 123”之类的数字,但是当我尝试添加 4 个七位数长的数字(7 位数,因为这是极端情况)时,它只会添加最多 23068。这听起来像是我的某个标签或其他东西的尺寸问题,但我不确定。
代码如下:
*
ORG [=10=]
DC.L 00 * Stack pointer value after a reset
DC.L start * Program counter value after a reset
ORG 00 * 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码转换成实际数字有关系。我add.l到结果标签。标签足够大,可以存储字符,但我没有向它移动足够大的块。
当我输入“9999999 9999999 9999999 9999999”并设置断点观看时,内存会正确显示26259FC的十六进制值,所以当我使用提供的宏将其转换回来时出现问题。
我不指望任何人对此有解决方案,但也许有人有。
编辑2:
此代码已在 Sep Rowland 的指导下进行了修订(非常感谢)。我想我得到了他涵盖的所有内容,修改后的代码已作为答案提交。
初始问题:
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 [=10=]
DC.L 00 * Stack pointer value after a reset
DC.L start * Program counter value after a reset
ORG 00 * 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
错误(您已经发现)是 ext.l D0
。鉴于此指令对 D0
中的低位字进行符号扩展,结果不一致也就不足为奇了。
我很少有机会深入研究一些好的 68K 代码,所以在这里我提出一些可以改进您的程序的评论。
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 消息,添加一个 space,添加几个字符长的结果,添加一个句点并添加一个零.显然是缓冲区溢出。
现在你可以让这个缓冲区更长,或者智能地停止复制周围的一切,只需将 result 缓冲区放在 sum 消息旁边(带有 space 追加且没有终止零)。然后一次性显示组合的 sum 和 result 文本。一个更简单的解决方案。
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
一直到 top,在那里您将不必要地进行 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:
编写此程序是为了接受 space 带四个标记的定界用户输入,如果它们都是数字,则将这些标记加在一起,并将结果打印到终端。现在它适用于诸如“1 1 1 1”和“123 123 123 123”之类的数字,但是当我尝试添加 4 个七位数长的数字(7 位数,因为这是极端情况)时,它只会添加最多 23068。这听起来像是我的某个标签或其他东西的尺寸问题,但我不确定。
代码如下:
*
ORG [=10=]
DC.L 00 * Stack pointer value after a reset
DC.L start * Program counter value after a reset
ORG 00 * 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码转换成实际数字有关系。我add.l到结果标签。标签足够大,可以存储字符,但我没有向它移动足够大的块。
当我输入“9999999 9999999 9999999 9999999”并设置断点观看时,内存会正确显示26259FC的十六进制值,所以当我使用提供的宏将其转换回来时出现问题。
我不指望任何人对此有解决方案,但也许有人有。
编辑2: 此代码已在 Sep Rowland 的指导下进行了修订(非常感谢)。我想我得到了他涵盖的所有内容,修改后的代码已作为答案提交。
初始问题: 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 [=10=]
DC.L 00 * Stack pointer value after a reset
DC.L start * Program counter value after a reset
ORG 00 * 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
错误(您已经发现)是 ext.l D0
。鉴于此指令对 D0
中的低位字进行符号扩展,结果不一致也就不足为奇了。
我很少有机会深入研究一些好的 68K 代码,所以在这里我提出一些可以改进您的程序的评论。
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 消息,添加一个 space,添加几个字符长的结果,添加一个句点并添加一个零.显然是缓冲区溢出。
现在你可以让这个缓冲区更长,或者智能地停止复制周围的一切,只需将 result 缓冲区放在 sum 消息旁边(带有 space 追加且没有终止零)。然后一次性显示组合的 sum 和 result 文本。一个更简单的解决方案。
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
一直到 top,在那里您将不必要地进行 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: