如何解决在 Arm 装配中实现选择排序时遇到问题
所以我的程序有问题。它应该在文本文件中读取 每行都有一个数字。然后将其存储在一个数组中,使用选择排序对其进行排序,然后将其输出到一个新文件中。读取和写入文件工作正常,但我的排序代码无法正常工作。当我运行程序时,它似乎只存储了一些数字 在数组中,然后是一堆零。
所以如果我的输入是 112323,32,12,19,2,1,23。输出是 0,23。我很确定问题出在我如何从数组中存储和加载 到寄存器上,因为假设那部分工作,我找不到选择排序算法不工作的任何原因。
好的,感谢您的帮助,我发现我需要更改加载和存储指令,使其与使用的说明符(ldr -> ldrb 和 str -> strb)相匹配。但是我需要制作一个适用于 32 位数字的排序算法,以便说明符和加载/存储指令的哪种组合允许我这样做?还是我必须一次加载/存储 8 位?如果是这样,我该怎么做?
.data
.balign 4
readfile: .asciz "myfile.txt"
.balign 4
readmode: .asciz "r"
.balign 4
writefile: .asciz "output.txt"
.balign 4
writemode: .asciz "w"
.balign 4
return: .word 0
.balign 4
scanformat: .asciz "%d"
.balign 4
printformat: .asciz "%d\n"
.balign 4
a: .space 32
.text
.global main
.global fopen
.global fprintf
.global fclose
.global fscanf
.global printf
main:
ldr r1,=return
str lr,[r1]
ldr r0,=readfile
ldr r1,=readmode
bl fopen
mov r4,r0
mov r5,#0
ldr r6,=a
loop:
cmp r5,#7
beq sort
mov r0,r4
ldr r1,=scanformat
mov r2,r6
bl fscanf
add r5,r5,#1
add r6,r6,#1
b loop
sort:
mov r5,#0 /*array parser for first looP*/
mov r6,#0 /* #stores index of minimum*/
mov r7,#0 /* #temP*/
mov r8,#0 /*# array parser for second looP*/
mov r9,#7 /*# stores length of array*/
ldr r10,=a /*# the array*/
mov r11,#0 /*#used to obtain offset for min*/
mov r12,#0 /*# used to obtain offset for second parser access*/
loop3:
cmp r5,r9 /*# check if first parser reached end of array*/
beq write /* #if it did array is sorted write it to file*/
mov r6,r5 /*#set the min index to the current position*/
mov r8,r6 /*#set the second parser to where first parser is at*/
b loop4 /*#start looking for min in this subarray*/
loop4:
cmp r8,r9 /* #if reached end of list min is found*/
beq increment /* #get out of this loop and increment 1st parser**/
lsl r7,#3 /*multiplies min index by 8 */
ADD r7,r10,r7 /* adds offset to r10 address storing it in r7 */
ldr r11,[r7] /* loads value of min in r11 */
lsl r7,r8,#3 /* multiplies second parse index by 8 */
ADD r7,r7 /* adds offset to r10 address storing in r7 */
ldr r12,[r7] /* loads value of second parse into r12 */
cmp r11,r12 /* #compare current min to the current position of 2nd parser !!!!!*/
movgt r6,r8 /*# set new min to current position of second parser */
add r8,#1 /*increment second parser*/
b loop4 /*repeat */
increment:
lsl r11,#3 /* multiplies first parse index by 8 */
ADD r11,r11 /* adds offset to r10 address stored in r11*/
ldr r8,[r11] /* loads value in memory address in r11 to r8*/
lsl r12,#3 /*multiplies min index by 8 */
ADD r12,r12 /*ads offset to r10 address stored in r12 */
ldr r7,[r12] /* loads value in memory address in r12 to r7 */
str r8,[r12] /* # stores value of first parser where min was !!!!!*/
str r7,[r11] /*# store value of min where first parser was !!!!!*/
add r5,#1 /*#increment the first parser*/
ldr r0,=printformat
mov r1,r7
bl printf
b loop3 /*#go to loop1*/
write:
mov r0,r4
bl fclose
ldr r0,=writefile
ldr r1,=writemode
bl fopen
mov r4,=a
loop2:
cmp r5,#7
beq end
mov r0,=printformat
ldrb r2,[r6]
bl fprintf
add r5,#1
b loop2
end:
mov r0,=a
ldr r0,[r0]
ldr lr,=return
ldr lr,[lr]
bx lr
解决方法
我发现我需要更改加载和存储指令 以便它匹配使用的说明符(ldr -> ldrb 和 str -> strb)。 但我需要制作一个适用于 32 位数字的排序算法 那么说明符和加载/存储指令的哪种组合会 允许我这样做吗?
如果你想从内存中读取 32b(4 个字节)的值,你必须在内存中有 4 个字节的值才能开始。嗯,这应该不足为奇:)
例如,如果您的输入是数字 1
、2
、3
、4
,则每个数字都是 32b 值,而在内存中则为
0x00000000: 01 00 00 00 | 02 00 00 00 <- 32b values of 1 & 2
0x00000008: 03 00 00 00 | 04 00 00 00 <- 32b values of 3 & 4
在这种情况下,ldr
每次都会读取 32b,并且每次读取寄存器都会得到 1、2、3、4。
现在,您在内存中拥有字节值(基于您的声明,即`ldrb` 给出了正确的结果),例如
0x00000000: 01
0x00000001: 02
0x00000002: 03
0x00000003: 04
or same in one line
0x00000000: 01 02 03 04
所以通过 ldrb
读取 8bit 会给你数字 1,2,3,4
但是 ldr
会从内存中读取 32b 值(一次全部 4 个字节),并且您会在寄存器中获得 32b 值 0x04030201
。
注意:小端系统示例
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。