【问题标题】:Why does the C "long" data type compile to two MSP430 ".word"s?为什么 C“long”数据类型编译为两个 MSP430“.word”?
【发布时间】:2020-08-21 03:53:42
【问题描述】:

我明白:

char (1 byte)
short (2 bytes)
long (4 bytes)
long long (8 bytes)

但是在将 C 转换为汇编时,为什么会有额外的 .word 0.word -1

【问题讨论】:

  • 两个 16 位 .word 值创建一个 32 位 two's complement 值(在“小端”endianness 中)?
  • 您想知道为什么有两个(考虑一个单词的大小)还是想知道为什么它们具有它们所具有的值?
  • 简短的回答是因为 msp430 是 16 位平台。

标签: c assembly msp430


【解决方案1】:

C 变量类型的大小取决于作者对该编译器和目标的选择。根据定义,没有固定的规则。对于一个(版本)编译器,一个 int 可以是一个目标的 16 位和另一个目标的 32 位。对于两个不同的编译器,相同的目标一个可以选择 16 位另一个 32 位。并且大小不必与通用寄存器大小一致 - 作者的选择。

这就是 stdint.h 的全部内容,它最终是编译器的一部分,并将 8、16、32、64 等大小之间的点与编译器为该目标选择的大小连接起来,一个特定版本的例如,用于 x86 的 stdint.h 的 gcc 预计不会与相同版本的 gcc msp430 stdint.h 兼容。

这里发生的事情正如你所描述的那样。

char (1 byte)
short (2 bytes)
long (4 bytes)
long long (8 bytes)

汇编语言特定于汇编器,工具,而不是目标,汇编器的作者可以选择他们选择的任何语法和助记符等。与芯片文档有些相关是理智的道路,但肯定没有汇编语言的规则。特别是您如何定义数据项。在这里,.word 表示 16 位值,.byte 表示 8 位值。

2048 = 0x0000....00800
-2048 = 0xFFFF....FF800

所以如果你剪掉 2048 的低 8 位你得到 0x00,你砍掉低 16 位你得到 0x0800,低 32 位你得到 0x00000800,所以

.byte 0x00

.word 0x0800

假设小端:

.word 0x0800
.word 0x0000

适用于 8、16 和 32 位

十进制:

.byte 0

.word 2048

.word 2048
.word 0

.word 2048,0

取决于汇编器的语法

对于负版-2048

.byte 0x00

.word 0xF800

.word 0xF800
.word 0xFFFF

对于该数字的 8、16 和 32 位版本

十进制

.byte 0

.word -2048

.word -2048
.word -1

一个 long long -2048 将是

.word -2048
.word -1
.word -1
.word -1

或 long long -2048 也可以实现为:

.byte 0
.byte -8
.byte -1
.byte -1
.byte -1
.byte -1
.byte -1
.byte -1

两者都在二进制文件中生成完全相同的数据。

【讨论】:

  • 我当然假设汇编器将十六进制识别为 0x1234 而不是 $1234 或 1234h 或其他如果它完全支持十六进制值。
  • 假设这是 GCC 输出,它是 GAS 语法,所以是的,这是一个很好的假设; GAS 使用 0x1234 表示十六进制常量,并且无法识别其他方式。
  • 如您所知,我试图对汇编语言提出一个通用的观点,语法确实暗示了气体,是的,这暗示了 C 风格的十六进制语法。 OP 没有在问题中提供足够的信息以获得明确的答案。
  • 各种类型必须能够表示最小范围内的值 - int 必须能够表示至少范围内的值@ 987654333@,表示它必须至少 16 位宽。它可能更宽,可能有填充位,但它必须包含至少 16 个值位。实施者在如何将这些需求映射到硬件上确实有很大的余地,但这并不是完全免费的。
  • 很公平,感谢您的澄清,因为它不死板,但不像我声称的那样灵活也是很好的信息。
【解决方案2】:

我不确定,但我认为您的问题是您了解其他 CPU(例如 x86)上的汇编程序,并且您假设 .word 是 32 位字。

但是,.word.long 等汇编语句和 C 数据类型 (!) 都是特定于处理器甚至特定于操作系统的。

示例:long 在 x86-64 Windows 上表示 4 个字节,在 x86-64 Linux 上表示 8 个字节; char 在 x86 上表示一个字节,在 MSP320F28x 上表示两个字节。

在 MSP430 上,.word 语句显然表示 16 位,而.long 语句在您使用的汇编程序中似乎不存在。

由于 C 数据类型 long 在 MSP430 上是 32 位,因此 long 类型的一个变量需要两个 .word 语句(2x16 位)。

【讨论】:

    【解决方案3】:

    MSP430 是 16 位 CPU,因此它不支持 32 位数字的硬件。因此,与任何此类低端 MCU 一样,它必须依赖软件库来处理更大的类型——一旦您使用 32 位算术,编译器就会在您的代码中内联此功能。这就是为什么 32 位算法在 16 个苦味上效率低下,而在 8 个苦味上非常效率低下的原因。

    术语“单词”相当宽泛,但通常是指 CPU 可以存储在数据寄存器中并在单个指令中处理的最大数据块。这个“字长”使您的 MSP430 成为“16 位”。在 C 语言中,一个“单词”对应于类型int,因此在这个系统上是 16 位。

    在 C 中编程时知道int 的大小和范围非常重要,因为这会影响整数常量123 的类型,用于隐式提升小整数类型的类型等等。

    尽管在对嵌入式系统进行编程时,您永远不应该明确使用这些类型中的任何一种,但您应该使用来自stdint.h 的类型。

    【讨论】:

      猜你喜欢
      • 2011-11-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-30
      • 1970-01-01
      • 1970-01-01
      • 2016-03-27
      • 2020-09-21
      相关资源
      最近更新 更多