2

アセンブリ プログラミングは初めてで、ARM 用にプログラミングしています。メモリ内のバイト ベクトルにバイト情報を追加するサブルーチンと、このベクトルを出力するサブルーチンの 2 つのサブルーチンを使用してプログラムを作成しています。ベクトルの最初のアドレスには、最大 255 までの要素数が含まれます。GDB でデバッグすると、「appendbyte」サブルーチンが正常に動作することがわかります。しかし、「printvector」に関しては、いくつかの問題があります。まず、レジスタ r1 にロードされた要素が間違っています (7 であるべきところに 0 をロードします)。次に、「printf」関数を使用した後にGDBでレジスタ値を読み取ると、多くのレジスタが変更されないはずの他の値を取得します。それらを変更しなかったため、「printf」を使用しただけです。「printf」が値を変更するのはなぜですか。

アラインメントのことを考えていました。ディレクティブを正しく使用しているかどうかはわかりません。

完全なコードは次のとおりです。

    .text
    .global main    
    .equ    num, 255    @ Max number of elements

main:
    push    {lr}

    mov r8, #7
    bl appendbyte
    mov r8, #5
    bl appendbyte
    mov r8, #8
    bl appendbyte
    bl imprime

    pop {pc}

.text
.align  

printvector:
    push {lr}

    ldr r3, =vet @ stores the address of the start of the vector in r3
    ldr r2, [r3], #1 @ stores the number of elements in r2

.align  
loop:
    cmp r2, #0 @if there isn't elements to print
    beq fimimprime @quit subroutine
    ldr r0, =node   @r0 receives the print format
    ldr r1, [r3], #1 @stores in r1 the value of the element pointed by r3. Increments r3 after that.
    sub r2, r2, #1 @decrements r2 (number of elements left to print)
    bl printf @call printf
    b loop @continue on the loop

.align  
endprint:
    pop {pc}

.align  
appendbyte:
    push {lr}

    ldr r0, =vet    @stores in r0 the beggining address of the vector
    ldr r1, [r0], #1    @stores in r1 the number of elements and makes r0 point to the next address
    add r3, r0, r1  @stores in r3 the address of the first available position
    str r8, [r3]    @put the value at the first available position
    ldr r0, =vet    @stores in r0 the beggining address of the vector
    add r1, r1, #1  @ increment the number of elements in the vector
    str r1, [r0]    @ stores it in the vector

    pop {pc}

.data           @ Read/write data follows
.align          @ Make sure data is aligned on 32-bit boundaries
vet:    .byte 0
    .skip   num     @ Reserve num bytes

.align
node:   .asciz "[%d]\n"

.end

問題は

    ldr r1, [r3], #1

    bl printf

問題が明確だったことを願っています。前もって感謝します!

4

2 に答える 2

3

ARM ABI は、レジスタ r0 ~ r3 および r12 が関数呼び出しで揮発性と見なされることを指定します。呼び出し先が値を復元する必要がないことを意味します。bl を使用すると、LR も変更されます。これは、呼び出された関数の戻りアドレスが LR に含まれるためです。

詳細については、ABIに関する ARM インフォメーション センターのエントリ、またはAPCS (ARM Procedure Call Standard) ドキュメントを参照してください。

于 2013-10-14T12:29:10.870 に答える
0
printvector:
    push {lr}

    ldr r3, =vet @ stores the address of the start of the vector in r3
    ldr r2, [r3], #1 @ stores the number of elements in r2

.align  
loop:
    cmp r2, #0 @if there isn't elements to print
    beq fimimprime @quit subroutine
    ldr r0, =node   @r0 receives the print format
    ldr r1, [r3], #1 @stores in r1 the value of the element pointed by r3. Increments r3 after that.
    sub r2, r2, #1 @decrements r2 (number of elements left to print)
    bl printf @call printf
    b loop @continue on the loop

.align  
endprint:
    pop {pc}

それは絶対に整列の使用方法ではありません。Align は、ある境界 (オプションの引数で指定されます。これは命令ではなくアセンブラー ディレクティブであることに注意してください) に続くものを、ゼロまたはパディングでバイナリをパディングすることによって整列させるためにあります。したがって、命令間のコード フローで .align を使用する必要はありません。ループ後のldr r1とcmp r2の間でそれを行いました。分岐が無条件であるため、b ループ後のアラインは有害ではありませんが、アセンブラーが命令フローを生成しているため、アラインメントをアラインする理由がないため、バイトをアンアラインすることはできません。.align を使用する場所は、命令の前のデータ宣言の後です。

.byte 1,2,3,4,5,
.align
some_code_branch_dest:

特に、アセンブラが文句を言うか、コードがクラッシュする場所です。

于 2013-10-14T13:26:31.747 に答える