ASM内联汇编气泡排序;需要恒定值,行尾有垃圾

如何解决ASM内联汇编气泡排序;需要恒定值,行尾有垃圾

我有一个用C编写的Arduino MEGA程序,该程序用随机整数填充数组,然后调用用ASM内联汇编编写的冒泡排序算法。然后将排序后的整数转换为二进制,并点亮八个LED,每个LED对应于二进制数的一位。

首先,声明的全局变量。

const byte arraySize = 10;
volatile byte randomNums[arraySize]; 
volatile byte limit = arraySize-1;
volatile byte counter = 1;
volatile byte iteration = 1;

接下来,是主程序循环(为简单起见,我将省略二进制转换和LED代码)。

void loop() {

    for (int i = 0; i < arraySize; i++) {
        randomNums[i] = random(255);
    }

    // asm inline bubble sort here
}

最后,ASM内联汇编中的冒泡排序算法。

asm volatile(

    "               lds        r20,(limit)        ; position before end of array \n"
    "               lds        r21,(counter)      ; counter for loop is defined i=0 \n"
    "               lds        r22,(iteration)    ; counter set for iteration of sort algorithm k=1 \n"
    "               mov        r21,r27            ; i=1 \n"
    "               mov        r22,r28            ; iteration number in r28=k \n"
    "               lds        r23,(randomNums)   ; point to beginning of array by r23 'element' \n"
    "               mov        r23,r24            "
    "               add        1,r24              ; point to 'neighbour' \n"
    
    " check%=:      mov        r23,r25            ; get 'element' and place in r25 \n"
    "               mov        r24,r26            ; get 'neighbour' in array in r26 \n"
    "               cp         r25,r26            ; compare both values \n"
    "               brge       swap%=              ; swap the numbers \n"
    "               add        1,r23              ; increment pointer r23 \n"
    "               add        1,r24              ; increment pointer r24 \n"
    "               add        1,r27              ; increment loop counter \n"
    "               eor        r27,(limit)        ; xor check if not exceeding array size \n"
    "               brne       check%=             "
    
    " swap%=:       mov        r23,r24            ; swap content where index r23 is pointing to where index r24 is pointing \n"
    "               mov        r26,r23            ; move greater number to position after smaller number \n"
    "               add        1,r28              ; increment loop counter \n"
    "               cp         r28,(arraySize)    ; check not exceeding array capacity \n"
    "               ret                            "         
                              
    ::: "r20","r21","r22","r23","r24","r25","r26","r27","r28"); // clobbered registers

注释掉该程序集后,程序将工作(保存为排序)。当我用程序集编译程序时,出现以下晦涩的错误。

C:\Users\USERNAME\AppData\Local\Temp\cc2d2uAp.s: Assembler messages:
C:\Users\USERNAME\AppData\Local\Temp\cc2d2uAp.s:1963: Error: garbage at end of line
C:\Users\USERNAME\AppData\Local\Temp\cc2d2uAp.s:1971: Error: constant value required
C:\Users\USERNAME\AppData\Local\Temp\cc2d2uAp.s:1972: Error: garbage at end of line
C:\Users\USERNAME\AppData\Local\Temp\cc2d2uAp.s:1977: Error: constant value required
lto-wrapper.exe: fatal error: E:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avr-gcc returned 1 exit status
compilation terminated.
e:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/7.3.0/../../../../avr/bin/ld.exe: error: lto-wrapper failed
collect2.exe: error: ld returned 1 exit status
exit status 1
Error compiling for board Arduino Mega ADK.

我已经在线搜索并查看了AVR组装手册,但无法弄清楚这些错误的含义以及发生的位置。我要补充一点,我是AVR组装和ASM内联的新手。

解决方法

“行末垃圾”问题是由于行末缺少\n个字符引起的。其中有三行,但我怀疑第三行还可以,因为它在末尾。

另外两个问题与以下几行有关,我认为这些行不能具有内存操作数:

eor r27,(limit)
cp  r28,(arraySize)

这两行之间的行号差异与生成的错误中的差异(1977 - 1971匹配,一旦考虑到以下两行,由于缺少这些行,它们被视为 one \n在第一个:

"               brne       check%=   "
" swap%=:       mov        r23,r24  ; swap content ... \n'

顺便说一句(正如杰斯特在评论中指出的那样),看起来Atmel没有拥有立即操作数ADD指令(请参阅here) ,因此请注意以下形式的说明:

add 1,r27

允许这样做的可能性有很多:

  • 您当前的错误可能会掩盖问题;
  • 在将其视为add r1,r27的嵌入式汇编程序中可能是一个缺陷;
  • 它可能是嵌入式汇编程序中的功能,因为它可能正在生成代码以模仿此操作。

关于最后一点,我已经看过以前做过的事情,例如“多寄存器推送”:

push r1,r7,r42

它仅组合为三个单寄存器推送。

可能是汇编程序足够聪明,可以将add 1,r27转换为inc r27。由于您要添加的唯一立即值是1,因此有可能。

这也指出了可能的解决方案,如果事实证明这是一种缺陷,并且错误地将r1而不是1添加到r27。只需将这些add指令变成inc指令即可。


仅对代码 logic 进行注释,而不仅仅是对语法进行注释,我不确定您是否正确地将指针和内容概念正确分离了。看来r23/24randomNums数组中单元格的地址,但指令:

lds r23,(randomNums)

会将该数组的第一个加载到寄存器中。因此,请考虑:

                    +---+---+---+---+
randomNums @ 0x1000 | 4 | 2 | 3 | 1 |
                    +---+---+---+---+

您使用的指令将r23设为值4,而不是地址1000ldi指令是您用来加载立即数的指令。


即使修复了该问题,也可以使用以下方法提取值:

mov r23,r25
mov r24,r26

不起作用,因为您正在传输地址,而不是使用这些地址获取进行比较。

使用寄存器间接加载值通常是通过将该寄存器加载到lpm指令(例如ZR30/31)可以使用的寄存器中来完成的。


此外,当您将分支 转到swap时,您从那里返回意思是即使您设置了正确的地址,您最多也可以交换一对元素。

一种解决方法是将调用 swap作为子例程,而不是分支到该子例程,然后对其进行修改,以使其仅 交换并返回,从而删除注册操作和比较-应该在主代码中重新完成。

另一个(在我看来,更可取)是将其视为if语句,而只是跳过交换的代码,例如:

           cp    r25,r26      ; compare both values.
           brle  noswap%=      ; skip swap if already ordered.

           @swap (r25),(r26)  ; actual code to swap goes here.
noswap%=:
           add        1,r23   ; carry on with loop.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-