英文:
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:
-
I changed the comment at the beginning to reflect the new objective, which is copying values divisible by 3.
-
I replaced the
cnt
variable and associated comments with a temporary variable$15FE
to store the loop counter. -
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.
- I loaded the first element from the array into B using
-
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位A
和B
寄存器组合而成的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
一样继续执行)。
- 这将需要一个2条指令的序列,第一条指令将
有一些寄存器冲突:为了使用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-bitA
&B
registers. HCS12 is big endian, andA
is the high order, whileB
is the low order of pairD
. (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 thatA
is clear (zeroes) to widen the unsigned byte data from 8-bits to 16-bits in alias register namedD
. -
Also you need to be aware that the byte data you want to put into
B
is referred to by theX
register. -
So, you'll use an instruction like
LDAB
(but also you'll need to make sureA
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 theD
-
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 labelyes
if the compare says zero, e.g. usingBEQ
(and if the compare fails it will fall through just like when thebrclr
falls through.
- This will require a 2-instruction sequence, where the first instruction compares
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论