2017-09-23 17 views
0

私はARMアセンブリの初心者です(アセンブリも一般的です)。今、私はプログラムを書いています。その最も重要な部分の1つは、ユーザーが手紙を入力する必要があり、次にその手紙を他の事前入力された手紙と比較して、ユーザーが同じものを入力したかどうかを確認しますもの。例えばユーザ入力の文字列/文字を別の文字列/文字と比較する

、私のコードで私は、ファイルの一番下にあるファイルの先頭に

.balign 4 /* Forces the next data declaration to be on a 4 byte segment */ 
dime: .asciz "D\n" 

addr_dime    : .word dime 

を持っています。

はまた、私はオンライン読んでてきたものに基づいて、私は、ファイルの先頭に

​​

を入れて、ファイルの一番下に

inputVal    : .word 0 

を置きます。

ldr r3, addr_dime 
ldr r2, addr_inputChoice 
cmp r2, r3     /*See if the user entered D*/ 
addeq r5, r5, #10   /*add 10 to the total if so*/ 
:ファイル(ちょうどこのスタンドアロンコードに問題があることを私を信頼し、ファイルの残りの部分は、このコンテキストでは関係ありません)私はこのコードのブロックを持っているの中央付近

私はr3に "D"をロードして、ユーザがr2に入力した文字列や文字をロードし、同じ場合はr5に10を加えてください。

何らかの理由でこれはうまくいかず、r5、r5、#10コードはaddneがその前に来る場合にのみ機能します。

答えて

0

addr_dime : .word dimeはpoitlessly over-complexです。アドレスはすでにリンク時定数です。メモリ内にアドレスを格納すると(それ自身のアドレスを持つ別の場所で)、まったく助けにならないだけで間接指示の別のレイヤーが追加されます。 (実際には問題の原因です)

とにかく、 cmpは、そのレジスタのオペランドを逆参照しないので、ポインタを比較しています。デバッガでシングルステップすると、レジスタ内の値がポインタであることがわかります。

R3にゼロ拡張、dimeで1バイトをロードするには、32ビットのロードを行うためにldrを使用し

ldrb r3, dime 

を行うことも\nバイトになるだろう、と32ビットの比較が持っているでしょうeqがtrueになるように一致させてください。

しかし、これは、PC相対アドレッシングモードに適合するには、dimeが十分に近い場合にのみ機能します。ほとんどのRISCマシンと同様、命令幅が固定であるため、ARMは任意の絶対アドレスを使用できません。

定数の場合、これを避ける最も簡単な方法は、ではなく、で、最初にメモリに格納します。その後、あなたはあなたのためのレジスタに定数を取得するためにアセンブラを依頼する

cmp r2, dime  @ compare with immediate operand 

またはldr r3, =dimeを使用することができ、数値定数を定義するために.equ dime, 'D'を使用してください。あなたはアドレスでこれを行うことができますので、あなたは、これはあまりにも遠く離れPC相対アドレッシングモードのためにあるかもしれない静的データからロードを処理するための汎用的な方法である

ldr r2, =inputVal  @ r2 = &inputVal 
ldrb r2, [r2]   @ load first byte of inputVal 

行うことができます。

スタックアドレス(sub sp, #16/mov r5, spなど)を使用することで回避できます。その後、あなたは既に登録簿に住所を持っています。


これは、Cコンパイラが何をするかを正確です:上の

ARM32のgcc6.3から
char dime[4] = "D\n"; 
char input[4] = "xyz"; 

int foo(int start) { 
    if (dime[0] == input[0]) 
     start += 10; 
    return start; 
} 

Godbolt compiler explorer

foo: 
     ldr  r3, .L4   @ load a pointer to the data section at dime/input 
     ldrb r2, [r3] 
     ldrb r3, [r3, #4] 
     cmp  r2, r3 
     addeq r0, r0, #10 
     bx  lr 
.L4: 
     @ gcc greated this "literal pool" next to the code 
     @ holding a pointer it can use to access the data section, 
     @ wherever the linker ends up putting it. 
     .word .LANCHOR0 

.section .data 
.p2align 2 
@@@ These are in a different section, near each other. 
@@@ On Godbolt, click the .text button to see full assembler directives. 

.LANCHOR0:  @ actually defined with a .set directive, but same difference. 
dime: 
     .ascii "D\012\000" 
input: 
     .ascii "xyz\000" 

ではなく、リテラル文字と比較するためにCを変更してみてくださいコンパイラが定数に最適化することができず、あなたが得るものを見ることができません。

+0

internal_relocation(type:OFFSET_IMM)が修正されていないというエラーが表示されます。 – PCRevolt

+0

@PCRevolt:ああ、ええ、アセンブラが魔法のようにデータに到達できるアドレッシングモードを使用するかどうか疑問に思いました。 ARMは固定長命令を使用し、任意の32ビット絶対アドレスのための余裕がありません。小さなオフセットを持つPC相対アドレッシングモードがあるため、ARMコードでは実際のコードの近くのブロックからデータを読み込むために "リテラルプール"を使用することがよくあります。 Cコンパイラの動作を参照してください:https://godbolt.org/g/xnRrNa。スタティックではなく、バッファ用にスタックメモリを使用した場合は、これを避けることができます。だからあなたはポインタと 'ldrb r3、[r5]'のアドレスを取得するだけです。 –

+0

しかし、このシナリオではr5は何でしょうか? – PCRevolt

関連する問題