2017-05-19 2 views
4

Ich mache ein paar nackte Knochen Programmierung für die Raspberry Pi und ich habe in ein seltsames Problem gerannt.Warum verschwindet ein Wert nach der Kompilierung mit gcc?

Ich brauche den Wert 0x80000000, um auf ein bestimmtes Bit zu testen. Grundsätzlich ist dieser Wert für eine Hardwareoperation, die ich mache, kritisch und kann nicht ersetzt werden. Wenn ich jedoch Assemblercode erzeuge, scheint die kritische Operation von (Status & 0x80000000) gelöscht zu werden. Das heißt, es gibt keine "und" -Operation irgendwo im Assemblercode. Wenn ich jedoch diese Zahl ändere, sage ich 0x40000000. Die Operation erscheint genau dort, wo ich es erwarten würde. Warum verschwindet diese Zahl besonders?

Das ist mein C-Code:

#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); 
} 

dies ist der Assembler-Code:

.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)" 

Antwort

5

Das Bit Sie testen sind, ist das höchste Bit in einer Integer-Variablen. Wenn Sie die Variable als vorzeichenbehaftete Ganzzahl behandeln würden, würde sie dem Vorzeichen-Bit entsprechen.

cmp r3, #0 
blt .L2 

Dieser Code vergleicht r3-0, und wenn es kleiner ist, springt zurück zu .L2. I.e. Die Schleifenbedingung lautet r3 < 0, was dem Testen entspricht, ob das Vorzeichenbit (= das höchste Bit) in r3 gesetzt ist.

+0

OHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH das mich so traurig macht. Ich dachte, das wäre die Quelle meines Fehlers, aber ja, was du sagst, ergibt vollkommenen Sinn. Ich weine jetzt ein bisschen. – Makogan

+0

@Makogan: Es wäre sinnvoll, diese Antwort zu akzeptieren, wenn es Ihr Problem löst. – Groo

1

Ich bin nicht wirklich vertraut mit dieser Assembler-Architektur. Aber der Code sieht gut für mich aus.

Bei einer Registergröße von 32 Bit und dem Speichern von Ganzzahlwerten als Zweierkomplement repräsentiert jeder Wert mit der höchsten Bitmenge einen negativen Wert, wenn er als Vorzeichen behandelt wird.

Daher ist der Compiler wandelt das UND in einen <0 Vergleich:

cmp r3, #0 
blt .L2 
+0

danke, ich verstehe, was jetzt passiert ist – Makogan

Verwandte Themen