Array copying in assembly

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Array copying in assembly

ソリューションへジャンプ
5,134件の閲覧回数
brunosmmm
Contributor II

Hello, as a learning exercise i'm trying to figure out how to do a memcpy-style implementation with only assembly.

 

I'm having trouble ordering my thoughts on how it should be performed. What would be a good starting point? I have difficulties trying to rationalize the process, as I am mainly C-oriented on my programming.

 

How should be stored and manipulated the addresses to the arrays' bytes (which would be incremented at each step)?

 

Remember, this is only a learning exercise. Any thoughts are aprreciated. Thanks.

ラベル(1)
タグ(2)
0 件の賞賛
返信
1 解決策
3,100件の閲覧回数
bigmac
Specialist III

Hello,

It is possible to create variables in RAM (equivalent to global variables) to store the current source and destination addresses, in addition to a byte counter.  However, the solution would be more general to make use of the stack to store these values.

The next issue is to "pass" the initial parameter values to the sub-routine.  The Accumulator and H:X registers are available, however these will be insufficient for the current requirement.  Therefore it will be necessary to "pre-load" some of the data to the stack, prior to the sub-routine call.

If the block size does not exceed 256 bytes, you might pass the block size within Acc, the destination address within H:X, and pre-load the source address.  However, for a block size that may exceed 256 bytes you will need to pass three 16-bit values.  For this case, one possibility is to pre-load the source and destination addresses, and to pass the block size within H:X.

The significance of pre-loading some of the data is that the stack pointer will require adjustment after the return from the sub-routine.

The following code snippet demonstrates the process.  The code should be compatible with CW assembler.

; Memory copy sub-routine
; Copy block of memory from source location to destination location.

; Source address and destination address values are pre-loaded to
; the stack prior to the sub-routine call.

; On entry, H:X contains the number of bytes to be copied.
; On exit, Acc value is preserved.

; Stack frame structure (SP index)
SRC       EQU    7              ; First pre-loaded value
DEST      EQU    5              ; Second pre-loaded value
COUNT     EQU    1              ; Byte count yet to be copied

MEMCOPY:  cphx   #0             ; Test for zero bytes to be copied
          beq    MC3            ; Exit if so
          psha                  ; Save current value
          pshx                  ; Save byte quantity to stack
          pshh
MC1:      ldhx   SRC,sp         ; Current source address
          lda    ,x             ; Fetch byte value
          ldhx   DEST,sp        ; Current destination address
          sta    ,x             ; Write byte value
          inc    SRC,sp         ; Increment source address
          inc    DEST,sp        ; Increment destination address
          ldhx   COUNT,sp       ; Byte counter
          beq    MC2            ; Exit if final byte copy done
          dec    COUNT,sp       ; Decrement byte count
          bra    MC1            ; Loop always for next byte

MC2:      ais    #2             ; Adjust stack pointer
          pula                  ; Restore previous value
MC3:      rts

; Typical usage:
;         aix    #-4            ; Create space on stack
;         ldhx   #SRC_ADDR
;         sthx   3,sp           ; Pre-load to stack
;         ldhx   #DEST_ADDR
;         sthx   1,sp           ; Pre-load to stack
;         ldhx   #BLOCK_SIZE
;         jsr    MEMCOPY
;         ais    #4             ; Adjust stack pointer

Regards,

Mac

元の投稿で解決策を見る

0 件の賞賛
返信
9 返答(返信)
3,101件の閲覧回数
bigmac
Specialist III

Hello,

It is possible to create variables in RAM (equivalent to global variables) to store the current source and destination addresses, in addition to a byte counter.  However, the solution would be more general to make use of the stack to store these values.

The next issue is to "pass" the initial parameter values to the sub-routine.  The Accumulator and H:X registers are available, however these will be insufficient for the current requirement.  Therefore it will be necessary to "pre-load" some of the data to the stack, prior to the sub-routine call.

If the block size does not exceed 256 bytes, you might pass the block size within Acc, the destination address within H:X, and pre-load the source address.  However, for a block size that may exceed 256 bytes you will need to pass three 16-bit values.  For this case, one possibility is to pre-load the source and destination addresses, and to pass the block size within H:X.

The significance of pre-loading some of the data is that the stack pointer will require adjustment after the return from the sub-routine.

The following code snippet demonstrates the process.  The code should be compatible with CW assembler.

; Memory copy sub-routine
; Copy block of memory from source location to destination location.

; Source address and destination address values are pre-loaded to
; the stack prior to the sub-routine call.

; On entry, H:X contains the number of bytes to be copied.
; On exit, Acc value is preserved.

; Stack frame structure (SP index)
SRC       EQU    7              ; First pre-loaded value
DEST      EQU    5              ; Second pre-loaded value
COUNT     EQU    1              ; Byte count yet to be copied

MEMCOPY:  cphx   #0             ; Test for zero bytes to be copied
          beq    MC3            ; Exit if so
          psha                  ; Save current value
          pshx                  ; Save byte quantity to stack
          pshh
MC1:      ldhx   SRC,sp         ; Current source address
          lda    ,x             ; Fetch byte value
          ldhx   DEST,sp        ; Current destination address
          sta    ,x             ; Write byte value
          inc    SRC,sp         ; Increment source address
          inc    DEST,sp        ; Increment destination address
          ldhx   COUNT,sp       ; Byte counter
          beq    MC2            ; Exit if final byte copy done
          dec    COUNT,sp       ; Decrement byte count
          bra    MC1            ; Loop always for next byte

MC2:      ais    #2             ; Adjust stack pointer
          pula                  ; Restore previous value
MC3:      rts

; Typical usage:
;         aix    #-4            ; Create space on stack
;         ldhx   #SRC_ADDR
;         sthx   3,sp           ; Pre-load to stack
;         ldhx   #DEST_ADDR
;         sthx   1,sp           ; Pre-load to stack
;         ldhx   #BLOCK_SIZE
;         jsr    MEMCOPY
;         ais    #4             ; Adjust stack pointer

Regards,

Mac

0 件の賞賛
返信
3,100件の閲覧回数
admin
Specialist II

I think there are a few oversights on bigmac's snippet:

* SRC and DST pointers are words, so you can't use INC (for example, use AIX #1 like in the code below)

* Similarly, use AIX #-1 (instead of DEC) for COUNT,SP

* Stack frame offsets are a bit off.

* Typical usage example should start with AIS #-4 (not AIX)

0 件の賞賛
返信
3,100件の閲覧回数
bigmac
Specialist III

Hello,

Guest wrote:

I think there are a few oversights on bigmac's snippet:

* SRC and DST pointers are words, so you can't use INC (for example, use AIX #1 like in the code below)

* Similarly, use AIX #-1 (instead of DEC) for COUNT,SP

* Stack frame offsets are a bit off.

* Typical usage example should start with AIS #-4 (not AIX)

Thank you for correcting these oversights.  The use of inc and dec instructions would have worked had I processed both low and high bytes of the address, which was not done.  However, your alternative suggestion does result in more efficient code.  Two of the stack frame offsets are actually a "byte" off - the accumulator value was pushed to the stack as an afterthought, without correspondingly adjusting the stack offset values.  The corrected code follows -

; Memory copy sub-routine
; Copy block of memory from source location to destination location.


; Source address and destination address values are pre-loaded to
; the stack prior to the sub-routine call.


; On entry, H:X contains the number of bytes to be copied.
; On exit, Acc value is preserved.


; Stack frame structure (SP index)
SRC       EQU    8              ; First pre-loaded value
DEST      EQU    6              ; Second pre-loaded value
COUNT     EQU    1              ; Byte count yet to be copied


MEMCOPY:  cphx   #0             ; Test for zero bytes to be copied
          beq    MC3            ; Exit if so
          psha                  ; Save current value
          pshx                  ; Save byte quantity to stack
          pshh
MC1:      ldhx   SRC,sp         ; Current source address
          lda    ,x             ; Fetch byte value
          aix    #1
          sthx   SRC,sp         ; Store incremented address
          ldhx   DEST,sp        ; Current destination address
          sta    ,x             ; Write byte value
          aix    #1
          sthx   DEST,sp        ; Store incremented address
          ldhx   COUNT,sp       ; Byte counter
          beq    MC2            ; Exit if final byte copy done
          aix    #-1
          sthx   COUNT,sp       ; Store decremented byte count
          bra    MC1            ; Loop always for next byte

MC2:      ais    #2             ; Adjust stack pointer
          pula                  ; Restore previous value
MC3:      rts


; Typical usage:
;         ais    #-4            ; Create space on stack
;         ldhx   #SRC_ADDR
;         sthx   3,sp           ; Pre-load to stack
;         ldhx   #DEST_ADDR
;         sthx   1,sp           ; Pre-load to stack
;         ldhx   #BLOCK_SIZE
;         jsr    MEMCOPY
;         ais    #4             ; Adjust stack pointer

Regards,

Mac

0 件の賞賛
返信
3,100件の閲覧回数
brunosmmm
Contributor II

Very clear answer, clean implementation made me understand the concept very easily. Thank you

0 件の賞賛
返信
3,100件の閲覧回数
tonyp
Senior Contributor II

Here's one example of a general-purpose copy routine.

(listing with macros expanded)


0 件の賞賛
返信
3,100件の閲覧回数
brunosmmm
Contributor II

Hello. Link is not working. Thanks.

0 件の賞賛
返信
3,100件の閲覧回数
tonyp
Senior Contributor II

There is a problem with our server.  They're doing some maintenance.  Try refreshing the page a few times, or a bit later.

0 件の賞賛
返信
3,100件の閲覧回数
brunosmmm
Contributor II

I wasn't able to fully understand your code syntax. When I have some more time I'll try to get t working.

0 件の賞賛
返信
3,100件の閲覧回数
DavidS
NXP Employee
NXP Employee

Hi Bruno,

I you have CW10 installed, please look at:

C:\Freescale\CW MCU v10.3\MCU\Help\PDF\HCS08-RS08_Assembler_MCU_Eclipse.pdf

Regards,

David

0 件の賞賛
返信