【问题标题】:Access array defined in inline assembler from C从 C 的内联汇编程序中定义的访问数组
【发布时间】:2015-11-04 11:49:27
【问题描述】:

我在 Assembler 中声明了一个整数,我在 C 中以下列方式使用它:

asm(
            "number:    \n"
            ".long 0xFFFFFFFF \n
);

extern int number;
int main(){
    //do something with number
}

现在我想在 Assembler 中声明一个 32 字节的数组。我尝试了以下方法:

asm(
            "number:    \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
);

extern unsigned char* number;
int main() {
    printf("%x ", number[0]); //gives segmentation fault
}

我不太了解 Assembler,但我必须使用这个特定的变量。

【问题讨论】:

  • 声明是不够的。您需要定义它。并且:你不能在 Assembler 中定义一个 integer;汇编程序没有数据类型的概念。如果那将是 32 位数据,您是否在 C 代码中将其声明为char? (而且“我必须使用……有人用枪指着你?)
  • 您为什么认为unsigned char * 是对的?这对我来说毫无意义,根本。也许是extern int number[8];,但我真的很紧张。
  • 如果你声明unsigned char *number,那意味着number处的值代表了一个地址或一个指针。在这种情况下,该地址或指针是0xFFFFFFFF。然后,当您将其取消引用为number[0] 时,您正在尝试引用地址0xFFFFFFFF 中的任何内容,这是无效的。尝试 "number: my_array\n" 后跟 "my_array:\n" prefacing your list of .long` 值。或者试试@unwind 建议的方法。
  • 您想要 32 个 byte 值还是 32 个 bit 值?
  • @Linus,32 字节。根据 unwind 的评论,我将其声明为 extern unsigned char number[32]。

标签: c gcc assembly x86 inline-assembly


【解决方案1】:

你的内联汇编器会这样做

asm(
            "number:    \n"
            ".long 0xFFFFFFFF \n"
            [snip rest of array]
);

然后你告诉 C number

extern unsigned char* number;

这表示 number 是一个指向无符号字符的指针。然后你像这样访问它:

printf("%x ", number[0]);

这表示取消引用 number 中的指针并返回第一个字符。这和做的一样:

printf("%x ", *(number+0));

问题是 number 被定义为一个指针。假设 32 位指针转换为:

*(0xFFFFFFFF+0)

如果您遇到段错误,可能是因为您的程序无法访问地址 0xFFFFFFFF。

您可以将 extern 语句更改为:

extern unsigned char number[32];

现在 number 是一个由 32 个无符号字符组成的数组。我倾向于使用 inttypes.h 标头并将其声明为:

extern uint8_t number[32];

uint8_t 保证为 8 位(或 1 个字节)。另一方面,char 被定义为至少 8 位(但可以更多)。但是sizeof(char) 将始终返回 1。我更喜欢uint8_t(无符号 8 位整数),这样您就知道您正在处理 8 位值,这里似乎就是这种情况。我将代码修改为:

#include <stdio.h>
#include <inttypes.h>

__asm__(
            "number:    \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFE \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
            ".long 0xFFFFFFFF \n"
);

extern uint8_t number[32];

int main() {
    printf("%x ", number[0]);
    return 0;
}

另外请注意,如果您打算使用 GCC 作为 C99 进行编译(也适用于 GCC 的 C89),最好使用 __asm__ 而不是 asm,因为 GCC 的默认设置是禁用 asm 关键字(除非使用 -std=c99 选项时被 -fasm) 覆盖。

number 可能不是无符号字符数组的好名称。当必须有人来维护您的代码时,可能会造成混乱。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多