2017-05-19 3 views
4

私はラズベリーパイのためにいくつかの裸の骨をプログラミングしています。私は奇妙な問題に遭遇しました。gccでコンパイルした後に値が消えてしまうのはなぜですか?

特定のビットをテストするには値0x80000000が必要です。基本的に、この値は、私がやっているハードウェアの操作には重要であり、置き換えることはできません。ただし、アセンブリコードを生成すると、(状態& 0x80000000)のクリティカルな操作が削除されたようです。すなわち、アセンブリコードのどこにでも "and"演算がありません。しかし、その番号を変更すると、0x40000000となります。私はそれが期待される場所に操作と操作が正しく表示されます。なぜその数字は具体的に消え去っていますか?

これは私のCコードです:

#include <stdint.h> 

#define REGISTERS_BASE 0x3F000000 
#define MAIL_BASE 0xB880 // Base address for the mailbox registers 
// This bit is set in the status register if there is no space to write into the mailbox 
#define MAIL_FULL 0x80000000 
// This bit is set in the status register if there is nothing to read from the mailbox 
#define MAIL_EMPTY 0x40000000 

struct Message 
{ 
    uint32_t messageSize; 
    uint32_t requestCode; 
    uint32_t tagID; 
    uint32_t bufferSize; 
    uint32_t requestSize; 
    uint32_t pinNum; 
    uint32_t on_off_switch; 
    uint32_t end; 
}; 

struct Message m = 
{ 
    .messageSize = sizeof(struct Message), 
    .requestCode =0, 
    .tagID = 0x00038041, 
    .bufferSize = 8, 
    .requestSize =0, 
    .pinNum = 130, 
    .on_off_switch = 1, 
    .end = 0, 
}; 

/** Main function - we'll never return from here */ 
//int main(void) __attribute__((naked)); 
int _start(void) 
{ 

    uint32_t mailbox = MAIL_BASE + REGISTERS_BASE + 0x18; 
    volatile uint32_t status; 

    do 
    { 
    status = *(volatile uint32_t *)(mailbox); 
    } 
    while((status & 0x80000000)); 

    *(volatile uint32_t *)(MAIL_BASE + REGISTERS_BASE + 0x20) = ((uint32_t)(&m) & 0xfffffff0) | (uint32_t)(8); 

    while(1); 
} 

これはアセンブリコードです:

.cpu arm7tdmi 
    .fpu softvfp 
    .eabi_attribute 20, 1 
    .eabi_attribute 21, 1 
    .eabi_attribute 23, 3 
    .eabi_attribute 24, 1 
    .eabi_attribute 25, 1 
    .eabi_attribute 26, 1 
    .eabi_attribute 30, 6 
    .eabi_attribute 34, 0 
    .eabi_attribute 18, 4 
    .file "PiTest.c" 
    .global m 
    .data 
    .align 2 
    .type m, %object 
    .size m, 32 
m: 
    .word 32 
    .word 0 
    .word 229441 
    .word 8 
    .word 0 
    .word 130 
    .word 1 
    .word 0 
    .text 
    .align 2 
    .global _start 
    .type _start, %function 
_start: 
    @ Function supports interworking. 
    @ args = 0, pretend = 0, frame = 8 
    @ frame_needed = 1, uses_anonymous_args = 0 
    @ link register save eliminated. 
    str fp, [sp, #-4]! 
    add fp, sp, #0 
    sub sp, sp, #12 
    ldr r3, .L4 
    str r3, [fp, #-8] 
.L2: 
    ldr r3, [fp, #-8] 
    ldr r3, [r3] 
    str r3, [fp, #-12] 
    ldr r3, [fp, #-12] 
         <-THE AND OPERATION SHOULD BE HERE 
    cmp r3, #0 
    blt .L2 
    ldr r2, .L4+4 
    ldr r3, .L4+8 
    bic r3, r3, #15 
    orr r3, r3, #8 
    str r3, [r2] 
.L3: 
    b .L3 
.L5: 
    .align 2 
.L4: 
    .word 1057011864 
    .word 1057011872 
    .word m 
    .size _start, .-_start 
    .ident "GCC: (15:4.9.3+svn231177-1) 4.9.3 20150529 (prerelease)" 

答えて

5

あなたがテストしているビットは、整数変数で最上位ビットです。変数を符号付き整数として扱う場合は、符号ビットに対応します。

cmp r3, #0 
blt .L2 

は、このコードは0からr3比較し、それが小さいだ場合、バック.L2へジャンプします。私。ループ条件はr3 < 0であり、符号ビット(=最上位ビット)がr3に設定されているかどうかのテストに相当します。

+0

OHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHこれは、私はとても悲しいことができます。私はこれが私のエラーの原因だと思ったが、あなたが言うことは完璧な意味合いがある。 Immaは今少し泣いています。 – Makogan

+0

@Makogan:あなたの問題を解決するなら、この答えを受け入れるのが理にかなっています。 – Groo

1

私はそのアセンブラのアーキテクチャに精通していません。 しかし、コードは私にとってはうまく見えます。

レジスタサイズが32ビットで、整数値を2の補数として格納すると、最高ビットセットの値は符号付きとして扱われると負の値を表します。

そのため、コンパイラは変換し<0比較に:

cmp r3, #0 
blt .L2 
+0

ありがとう、私は今起こったことを理解する – Makogan

関連する問題