【问题标题】:Why is a value vanishing after compilation with gcc?为什么用 gcc 编译后值消失了?
【发布时间】:2017-05-19 07:30:48
【问题描述】:

我正在为树莓派做一些简单的编程,但遇到了一个奇怪的问题。

我需要值 0x80000000 来测试特定位。基本上,这个值对于我正在做的硬件操作是至关重要的,并且不能被替换。然而,当我生成汇编代码时, (status & 0x80000000) 的关键操作似乎被删除了。也就是说,汇编代码的任何地方都没有“与”操作。但是,如果我将该数字更改为 0x40000000。 and 操作出现在我期望的位置。为什么这个数字特别消失了?

这是我的 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)"

【问题讨论】:

    标签: c gcc assembly raspberry-pi arm


    【解决方案1】:

    您正在测试的位是整数变量中的最高位。如果您将变量视为有符号整数,它将对应于符号位。

    cmp r3, #0
    blt .L2
    

    此代码将r30 进行比较,如果更小,则跳回.L2。 IE。循环条件为r3 &lt; 0,相当于测试r3中是否设置了符号位(=最高位)。

    【讨论】:

    • OHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH这让我很难过。我认为这是我错误的根源,但是是的,你说的很有道理。我现在有点哭了。
    • @Makogan:如果它解决了你的问题,接受这个答案是有意义的。
    【解决方案2】:

    我对那个汇编器架构不是很熟悉。 但是代码对我来说看起来不错。

    给定一个 32 位的寄存器大小并将整数值存储为二进制补码,任何设置了最高位的值如果被视为有符号则表示负值。

    因此编译器将 AND 转换为 &lt;0 比较:

    cmp r3, #0
    blt .L2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-06
      • 2023-04-03
      • 1970-01-01
      • 2013-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多