Motorola 68000汇编字符串拼接子程序正确性与优化问询
Motorola 68000字符串拼接子程序的正确性与优化分析
问题背景
我编写了一个Motorola 68000汇编的字符串拼接子程序,接收两个带空终止符的输入字符串StringA("Hello")和StringB("World"),将拼接结果存入StringC。代码编译无错误,但不确定输出是否正确、实现逻辑是否严谨,同时有两个疑问:
- 子程序实现是否正确?
jsr和rts的使用是否是该场景下的最佳方式? - 代码是否可优化?有没有冗余指令可以移除?
编写的汇编代码
ORG $8000 StringA DC.B 'Hello',0 ; First string with null terminator StringB DC.B 'World',0 ; Second string with null terminator StringC DS.B 20 ; Buffer for the concatenated string (large enough?) START: lea.l StringA,a0 ; a0 -> "Hello" lea.l StringB,a1 ; a1 -> "World" lea.l StringC,a2 ; a2 -> Buffer for concatenation clr.b d0 jsr CopyA ; Call first subroutine SIMHALT CopyA: move.b (a0)+,d0 ; Load character from StringA into d0 ; Check if it is the null terminator beq.s CopyB ; If yes, start copying StringB move.b d0,(a2)+ ; Otherwise, copy character into StringC bra CopyA CopyB: move.b (a1)+,d0 ; Load character from StringB into d0 move.b d0, (a2)+ ; Copy it into StringC bne CopyB ; If the character is not null, continue copying rts ; Return from subroutine END START
问题解答
1. 子程序正确性与jsr/rts的使用
实现完全正确
你的代码逻辑没问题,最终StringC会得到"HelloWorld\0"的正确结果:
CopyA循环复制StringA的每个字符,碰到空终止符就跳转到CopyBCopyB会把StringB的所有字符(包括结尾的空终止符)都复制到StringC,直到复制到空终止符后退出返回
关于StringC的大小:算上两个字符串的字符和各自的空终止符,总共需要12字节,你分配了20字节,完全足够,不会出现缓冲区溢出问题。
jsr/rts使用合理但非必须
用jsr和rts把拼接逻辑封装成子程序是合理的——代码结构清晰,要是以后需要多次拼接字符串,直接调用就行。但如果这个拼接逻辑只需要执行一次,也可以把CopyA和CopyB的代码直接写到START里,省掉一次子程序调用的开销(虽然68000的这个开销不大,但追求极致性能的话可以这么做)。不过从可读性和维护性来说,封装成子程序是更好的选择。
2. 代码优化:移除冗余与精简逻辑
你的代码有两处可以优化的地方:
- 删除冗余的
clr.b d0START里的clr.b d0完全没用,因为进入CopyA后第一条指令就是move.b (a0)+,d0,直接覆盖了d0的内容,这条指令可以直接删除。 - 使用短分支节省指令长度
CopyA里的bra CopyA可以改成bra.s CopyA,用短分支指令(占2字节,长分支占4字节),因为CopyA是本地标签,短分支足够到达。同样CopyB里的bne CopyB也可以改成bne.s CopyB。
另外,CopyB还可以改成无需d0中转的写法,性能和原写法差不多,看你偏好可读性:
CopyB: move.b (a1)+,(a2)+ ; 直接把StringB的字符复制到StringC tst.b -(a2) ; 检查刚复制的字符是不是空终止符 bne.s CopyB ; 不是就继续 addq.l #1,a2 ; 把a2指针回退到正确位置
优化后的完整代码:
ORG $8000 StringA DC.B 'Hello',0 ; First string with null terminator StringB DC.B 'World',0 ; Second string with null terminator StringC DS.B 20 ; Buffer for the concatenated string (large enough?) START: lea.l StringA,a0 ; a0 -> "Hello" lea.l StringB,a1 ; a1 -> "World" lea.l StringC,a2 ; a2 -> Buffer for concatenation jsr CopyA ; Call first subroutine SIMHALT CopyA: move.b (a0)+,d0 ; Load character from StringA into d0 beq.s CopyB ; If null terminator, jump to copy StringB move.b d0,(a2)+ ; Copy character to StringC bra.s CopyA ; Short branch for efficiency CopyB: move.b (a1)+,d0 ; Load character from StringB into d0 move.b d0,(a2)+ ; Copy to StringC bne.s CopyB ; Continue if not null rts ; Return from subroutine END START
内容的提问来源于stack exchange,提问作者Pato
相关产品推荐
相关产品推荐

