How can I change this code from taking in numbers divisible by 4 to numbers divisible by 3? Assembly for mircoprocessors

huangapple go评论81阅读模式
英文:

How can I change this code from taking in numbers divisible by 4 to numbers divisible by 3? Assembly for mircoprocessors

问题

; Copy all the values which are divisible by three to a starting address $1600.
; The non-divisible by three values are pushed onto the stack, and use the effective address
; to pull them out after finishing the loop. The starting address is $1650.
; Array pointer starts from the beginning, and using DBNE to decrement the loop

N       equ     12
        org     $1600
        fill    0,128           ; each row in the memory displays 16 bytes
cnt     rmb     1               ; non-divisible counter
        org     $1ff0
        fill    0,16

        org     $2000           ; start RAM address
        lds     #$2000          ; initialize the stack pointer
        ldy     #$1600          ; load the starting address for divisible by 3
        ldx     #array          ; load the starting address of array to Reg. X
        ldaa    #N              ; use A as the loop counter, A = N
        clr     cnt             ; clear cnt counter
loop    clr     $15FE           ; clear the temporary address for loop counter
        ldab    0,y             ; load the first array element into B
        idiv                    ; divide D by X, result in D, remainder in B
        lbne    yes             ; if remainder (B) is non-zero, branch to yes
        pshb                    ; push B onto the stack for non-divisible
        ldx     $15FE           ; reload the updated address for divisible by 3
yes     inc     y               ; increment array pointer
        dbne    a,loop          ; decrement A by 1, if A NE 0, branch to loop

; use the effective address to load/pull the elements from the stack

        ldy     #$1650
        ldx     #$1fff          ; first available address for the stack
        ldaa    cnt
loop2   pshx                    ; push X onto the stack to use as an effective address
        pulb                    ; pull non-divisible value from the stack to B
        movb    1,x-,1,y+       ; copy the non-divisible value to a new location
        pshx                    ; push X back onto the stack
        dbne    a,loop2         ; decrement A by 1, if A NE 0, branch to loop2
        swi

array   db      3,4,9,12,19,20,24,31,48,53,64,72
        end

I've modified the given assembly code to copy values that are divisible by three to memory address $1600 and the non-divisible values are pushed onto the stack and then copied back after finishing the loop. Here's a brief explanation of the changes made:

  1. I changed the comment at the beginning to reflect the new objective, which is copying values divisible by 3.

  2. I replaced the cnt variable and associated comments with a temporary variable $15FE to store the loop counter.

  3. Inside the loop:

    • I loaded the first element from the array into B using ldab 0,y.
    • I used idiv to divide D by X (where X is 3). The remainder is stored in B, and D contains the result.
    • If the remainder (B) is non-zero, it means the value is non-divisible by 3, so I push it onto the stack.
    • If the remainder is zero, I reload the updated address for divisible by 3.
  4. After the loop, I use the effective address method to pull the non-divisible values from the stack and copy them to the new location.

Please note that assembly programming can be complex, and it's essential to understand the instructions and their operands. This code should help you copy values divisible by 3 to the desired memory location, but it's crucial to learn more about assembly language to gain a better understanding of how it works.

英文:

Code in question:

; Copy all the values which are divisible by four to a starting address $1600.
; The indivisible by four is pushed onto the stack, and use the effective address
; to pull them out after finishing the loop. The starting address is $1650.
; Array pointer starts from the beginning, and using DBNE to decrement the loop

N       equ     12
        org     $1600
        fill    0,128           ; each row in the memory displays 16 bytes
cnt     rmb     1               ; indivisible counter
        org     $1ff0
        fill    0,16

        org     $2000           ; start RAM address
        lds     #$2000          ; initialize the stack pointer
        ldy     #$1600          ; load the starting address for divisible by 4
        ldx     #array          ; load the starting address of array to Reg. X
        ldaa    #N              ; use B as the loop counter, B = N
        clr     cnt             ; clear cnt counter
loop    brclr   0,x,$03,yes     ; if bits 1 & 0 are 0s, then branch to yes
        ldab    1,x+
        inc     cnt             ; increment cnt counter for indivisible
        pshb                    ; push onto the stack for the indivisible
        bra     chkend
yes     movb    1,x+,1,y+       ; copy the divisible by 4 value to a new location
chkend  dbne    a,loop          ; decrement B by 1, if B NE 0, branch to loop

; use the effective address to load/pull the elements from the stack

        ldy     #$1650
        ldx     #$1fff          ; first available address for the stack
        ldaa    cnt
loop2   movb    1,x-,1,y+       ; stack is first in last out
        dbne    a,loop2
        swi
array   db      3,4,9,12,19,20,24,31,48,53,64,72
        end

I'm taking mircoprocessors and my professor gave us this code to change, but I'm unsure on how to. This is the first time we're "programming" in Assembly.

He also came us this to help:

EEEN 3449
Lab 4c:
• idiv => Accumulator D / Register X, the remainder refreshes to D
• Register X has the constant 3.
• Register Y is utilized as the array pointer.
• Although there is nothing stored in Accumulator A, A:B => D
• You can use Accumulator B as the loop counter, and store the
starting address for divisible by 3.
• In the beginning of the loop, you have to store loop counter value in
another temporary address, like $15FE.
• clr A, and ldab 0,y will generate [D] = [0 : 1st array element]
• Carry out the idiv and compare Accumulator D with 0.
• If Accumulator D is non-zero, push the accumulator B onto the stack.
• If Accumulator D is zero, reload the updated address for divisible by 3.
• After sorting out the array element where to store them, reload the
loop counter from $15FE, and increment the array pointer.
• Then use dbne b,loop to execute the next iteration.

Thanks to not knowing Assembly, I don't know how to use this to change the code correctly.

The code shown is pulling numbers that are divisble by 4 and putting them into the memory at $1600, I think. I need to change this code and make it pull numbers that are divisble by 3. No clue where to start and begin testing since I don't know a whole lot on Assembly.

Any help would be great as well as if you could help me understand what's happening. I do want to learn, but I can't seem to find much on Assembly.

I've tried testing things myself, but I keep getting errors and don't know where they are or how to fix them.

答案1

得分: 1

这段代码正在测试感兴趣的字节(由X寄存器引用)的低两位是否为零。这两位都为零意味着该数字可被4整除。当这个条件为真时,程序会转移到yes标签 - 所有这些都在一条指令中完成,即brclr

要从可被4整除更改为可被3整除,应使用idiv,并以一个条件分支结束,该分支将具有与brclr相同效果的分支到yes标签,条件为满足时分支到yes,否则跳过。

  • 首先,将要测试的数字放入D寄存器

    • 为此,您需要了解D寄存器是由8位AB寄存器组合而成的16位寄存器的别名。HCS12 是大端序,A是高位,B是配对D的低位。这种配对是架构固有的,无需其他操作来利用它。
    • 因为您的数据是字节数据(而不是16位数据),您需要将其加载到B中,并确保A清零(全为零),以将无符号字节数据从8位扩展到别名寄存器D中的16位。
    • 此外,您需要知道要放入B的字节数据由X寄存器引用。
    • 因此,您可以使用LDAB之类的指令(但还需要确保将A清零,例如,加载为0)。
  • 然后将常数3放入X寄存器。

  • 在设置好这些后,执行idiv,余数将在D中。

  • 执行与可被4整除相似的分支,但首先测试D = 0,如果比较结果为零,则跳转到yes标签。

    • 这将需要一个2条指令的序列,第一条指令将D与0进行比较并设置标志位,第二条指令如果比较结果为零则跳转到yes,例如,使用BEQ(如果比较失败,则像brclr一样继续执行)。

有一些寄存器冲突:为了使用idiv,您需要直接使用X寄存器,但代码已经在其他地方使用了X。建议在将X加载为3之前将X推入堆栈,然后在使用完后将其弹出,以便您可以保持其余的代码不变。看起来A也有相同的情况,它在该算法中用于计数,但也需要重新分配以使用idiv。您的指令提供了一些替代建议(而不是推入和弹出),您可以选择遵循这些建议。

英文:

That code is testing the low two bits of the byte of interest (referred to by the X register) for being zero.  Those bits both being zero means that the number is divisible by 4.  When that condition is true the program transfers control to label yes — all that is done in one instruction, the brclr.

To change from divisible by 4 to divisible by 3, you're supposed to use idiv in a sequence that ends with a conditional branch that will have the same effect as the brclr — which is to branch to label yes when the condition of interest holds, and fall through otherwise.

  • First, put the number you want to test in the D register

    • To do this, you need to know that the D register is an alias for the 16-bit register formed by pairing the 8-bit A & B registers.  HCS12 is big endian, and A is the high order, while B is the low order of pair D.  (This pairing is inherent in the architecture, you don't have to do anything else to take advantage of it.)

    • Because your data is byte data (not 16-bit data), you need to load it into B, and make sure that A is clear (zeroes) to widen the unsigned byte data from 8-bits to 16-bits in alias register named D.

    • Also you need to be aware that the byte data you want to put into B is referred to by the X register.

    • So, you'll use an instruction like LDAB (but also you'll need to make sure A is cleared, so load it with 0, for example).

  • Then put the constant 3 in the X register.

  • After setting that up, do an idiv and the remainder will be in the D

  • Do a similar branch as for the divisible by 4 but first test for D = 0, and in that case, branch to label yes.

    • This will require a 2-instruction sequence, where the first instruction compares D with 0 setting the flags, and the second branches to label yes if the compare says zero, e.g. using BEQ (and if the compare fails it will fall through just like when the brclr falls through.

There are some register conflicts: in order to use idiv you'll need to use the X register directly, but the code is already using X for something else.  Suggest before loading X with 3 to push X to the stack and pop it after so you can leave the rest of the code as is.  Looks like the same is true for A, which is holding the count in that algorithm, but also needs to be repurposed to use the idiv.  Your instructions make some alternative suggestions (rather than push and pop) you may choose to follow.

huangapple
  • 本文由 发表于 2023年3月7日 04:53:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75655741.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定