assembly 我在这个Microblaze组装气泡排序中做错了什么?

aemubtdh  于 2023-05-07  发布在  其他
关注(0)|答案(1)|浏览(181)

我正在为Basys 3 Microblaze的汇编语言编写一个程序。然而,这种语言与我在网上能找到的任何东西都大不相同。I have documentation for it here,从第4章(第65页)开始,我可以使用汇编命令。
我的代码需要从终端输入10个字符,每次输入后它会检查Basys上的开关并更改7段显示。但我不担心这个。我遇到麻烦的部分是这10个单字符输入存储在一个数组中。我需要遍历并对这个字符数组进行冒泡排序,然后再把它们吐出来。我有一个排序函数,应该这样做,但我只是不能让它工作。如果有人能帮我弄清楚我做错了什么,我将不胜感激。我整晚都在想办法。我使用Vivado 2019.1中的Xilinx SDK(以及以下版本,因为SDK在2019.2中被删除)。
下面是我的代码:

#Equates
.set NUMLOOPS, 10
.set SWITCH_DATA, 0x40000000
.set SEV_SEG_DATA, 0x40010000
.set UART, 0x40600000

#Memory Section
$msgBegin:
    .asciz "\r\n Program Start.\r\n"
    .text
    .align 2
$msgWithChar:
    .asciz  "Character %d - %c\r\n"
    .text
    .align  2
$Nums:
    .fill 10, 4, 65
    .data
    .align 4
$msgLoop:
    .asciz "\r\n Embedded Systems Loop #%2d.\r\n"
    .text
    .align 2
$msgEnd:
    .asciz "\r\n Program Stop.\r\n"
    .text
    .align 2
$msgTest1:
    .asciz "\r\n Test 1."
    .text
    .align 2
$msgTest2:
    .asciz "\r\n Test 2."
    .text
    .align 2
$msgTest3:
    .asciz "\r\n Test 3."
    .text
    .align 2
$msgSpace:
    .asciz "\r\n"
    .text
    .align 2

#Main Program
.globl  main
main:
    addi  r5, r0, $msgBegin # Store string to print
    addi  r1, r1, -4        # Push r15 onto stack
    swi   r15,r1, 0
    brlid r15,xil_printf    # Call print func; retn addr in r15
    nop                     # Unfilled delay slot
    lwi   r15,r1, 0         # Pop r15 off the stack
    addi  r1, r1, 4
    addi  r19, r0, NUMLOOPS # Initialize R19 to NUMLOOPS
    addi  r20, r0, 1        # Initialize R20 to one
    addi  r22, r0, 0        # Initialize R22 to 0
.globl  loop
loop:
    beqi  r19, sort         # If R19==0, branch to done; stop program
    nop
    rsub  r19,r20,r19       # Decrement loop counter (R19) by 1 (R20)
    lwi   r11, r0, SWITCH_DATA  # Read data from switches
    swi   r11, r0, SEV_SEG_DATA # Write switch data to 7-segment disp
    addi  r5, r0, UART      # Set R5 arg to UART memory address
    addi  r1, r1, -4        # Push r15 onto stack
    swi   r15, r1, 0
    brlid r15, XUartLite_RecvByte # Call UART Receive function
    nop
    lwi   r15, r1, 0        # Pop r15 off stack
    addi  r1, r1, 4
    swi   r3, r22, $Nums    # Store value into $Nums array at offset R22
    add   r6, r0, r3        # Move char R3 into R6 to display to UART
    addi  r1, r1, -4        # Push r15 on stack
    swi   r15, r1, 0
    brlid r15, XUartLite_SendByte # Call Uart Send function
    nop
    lwi   r15, r1, 0        # Pop r15 off stack
    addi  r1, r1, 4
    addi  r22, r22, 4       # Increment R22 by 4 bytes
    bri   loop
    nop

.globl sort
sort:
    addi r23, r0, 10        # Initialize R23 for outer loop counter
    addi r24, r0, 10        # Initialize R24 for inner loop counter
    addi r22, r0, 0         # Reinitialize R22 to zero
    addi r29, r0, 0         # Initialize R29 for address offset of a[0]

for1:
    #Print Test
    addi  r5, r0, $msgTest1 # Store string to print
    addi  r1, r1, -4        # Push r15 onto stack
    swi   r15,r1, 0
    brlid r15,xil_printf    # Call print func; retn addr in r15
    nop                     # Unfilled delay slot
    lwi   r15,r1, 0         # Pop r15 off the stack
    addi  r1, r1, 4

    beqid r23, disp            # If R23==0, branch to disp
    nop
    addi r23, r23, -1          # Decrement outer loop counter (R23) by 1
    addi r24, r0, 10   # Initialize R24 for inner loop counter
    addi r24, r24, -1           # Subtract 1 from R24 (since we are comparing i and i+1)

for2:
    #Print Test
    addi  r5, r0, $msgTest2 # Store string to print
    addi  r1, r1, -4        # Push r15 onto stack
    swi   r15,r1, 0
    brlid r15,xil_printf    # Call print func; retn addr in r15
    nop                     # Unfilled delay slot
    lwi   r15,r1, 0         # Pop r15 off the stack
    addi  r1, r1, 4

    beqid r24, for1            # If R24==0, branch to for1
    nop
    addi r24, r24, -1          # Decrement inner loop counter (R24) by 1
    addi r25, r0, 0            # Initialize R25 for address offset of a[i]
    muli r25, r24, 4 # Calculate address offset for a[i]
    lwi r26, r25, $Nums        # Load a[i] into R26
    addi r25, r25, 4 # Increment R25 for address offset of a[i+1]
    lwi r27, r25, $Nums        # Load a[i+1] into R27

    addi r28, r0, 0
    cmp r28, r26, r27
    bgtid r28, for2       # If a[i] > a[i+1], skip the swap
    nop

swap:
    #Print Test
    addi  r5, r0, $msgTest3 # Store string to print
    addi  r1, r1, -4        # Push r15 onto stack
    swi   r15,r1, 0
    brlid r15,xil_printf    # Call print func; retn addr in r15
    nop                     # Unfilled delay slot
    lwi   r15,r1, 0         # Pop r15 off the stack
    addi  r1, r1, 4

    swi r26, r25, $Nums        # Store R26 (a[i]) into a[i+1] location
    swi r27, r25, $Nums        # Store R27 (a[i+1]) into a[i] location (using R25 - ARRAY_OFFSET)
    rsubi r25, r25, -4
    bri for2
    nop


.globl  disp
disp:
    addi  r19, r0, NUMLOOPS # Reinitialize R19 to NUMLOOPS
    addi  r22, r0, 0        # Reinitialize R22 to zero
    addi  r5, r0, $msgSpace # 1st arg R5 is format string
    add   r6, r0, r22       # 2nd arg R6 is address offset
    lwi   r7, r22, $Nums    # 3rd arg R7 is array value at this offset
    addi  r1, r1, -4        # Push r15 on stack
    swi   r15, r1, 0
    brlid r15, xil_printf   # Call printf
    nop
    lwi   r15, r1, 0        # Pop r15 off stack
    addi  r1, r1, 4
.globl loop2
loop2:
    beqi  r19, done         # If R19==0, branch to done; stop program
    nop
    rsub  r19,r20,r19       # Decrement loop counter (R19) by 1 (R20)
    addi  r5, r0, $msgWithChar # 1st arg R5 is format string
    add   r6, r0, r22       # 2nd arg R6 is address offset
    lwi   r7, r22, $Nums    # 3rd arg R7 is array value at this offset
    addi  r1, r1, -4        # Push r15 on stack
    swi   r15, r1, 0
    brlid r15, xil_printf   # Call printf
    nop
    lwi   r15, r1, 0        # Pop r15 off stack
    addi  r1, r1, 4
    addi  r22, r22, 4       # Increment R22 by 4 bytes
    bri   loop2
.globl  done
done:
    addi  r5, r0, $msgEnd   # Store string to print
    addi  r1, r1, -4        # Push r15 onto stack
    swi   r15,r1, 0
    brlid r15,xil_printf    # Call print func; retn addr in r15
    nop                     # Unfilled delay slot
    lwi   r15,r1, 0         # Pop r15 off the stack
    addi  r1, r1, 4
jgzswidk

jgzswidk1#

beqi  r19, sort         # If R19==0, branch to done; stop program

应变为beqi r19, done

swi r26, r25, $Nums        # Store R26 (a[i]) into a[i+1] location
swi r27, r25, $Nums        # Store R27 (a[i+1]) into a[i] location (using R25 - ARRAY_OFFSET)
rsubi r25, r25, -4
bri for2
nop

不交换值。两家商店都在同一个地址。

swi r26, r25, $Nums        # Store R26 (a[i]) into a[i+1] location
addi r25, r25, -4
swi r27, r25, $Nums        # Store R27 (a[i+1]) into a[i] location
bri for2
nop

当前,您的代码正在处理外层循环的 * 每次 * 迭代的 * 所有 * 数组元素。在BubbleSort中,你应该在外部循环的每次迭代中减少1个元素。最大/最小值(取决于升序/降序)将移动(“冒泡”)到一个极端,你应该不再需要处理它。
因为你冒泡到数组的 * 开头 *(多么奇怪......),只要内部循环运行一次,它将是你不再需要考虑的第一个元素。
如果删除以下内容,编写正确的代码会更容易:

  • 您仅为验证目的而编写的临时输出
  • 冗余指令,如设置未使用的R22和R29

一种可能的解决方案

.globl sort
sort:
    addi r23, r0, 9     # Initialize R23 for outer loop counter
for1:
    beqid r23, disp     # If R23==0, branch to disp
    nop
    addi r24, r23, 0    # Initialize R24 for inner loop counter (ever smaller)
    addi r23, r23, -1   # Decrement outer loop counter (R23) by 1
    addi r25, r0, -4    # Initialize R25 for address offset of a[i]
for2:
    beqid r24, for1     # If R24==0, branch to for1
    nop
    addi r24, r24, -1   # Decrement inner loop counter (R24) by 1
    addi r25, r25, 4    # Calculate address offset for a[i]
    addi r26, r25, 4    # Calculate address offset for a[i+1]

    lwi r27, r25, $Nums # Load a[i] into R27
    lwi r28, r26, $Nums # Load a[i+1] into R28

    addi r29, r0, 0
    cmp r29, r27, r28
    bgtid r29, for2     # If a[i] > a[i+1], skip the swap
    nop
swap:
    swi r27, r26, $Nums # Store R27 (a[i]) into a[i+1]
    swi r28, r25, $Nums # Store R28 (a[i+1]) into a[i]
    bri for2
    nop

.globl  disp
disp:

相关问题