从 C 访问内联汇编程序中定义的数组
Access array defined in inline assembler from C
我在汇编程序中声明了一个整数,我在 C 中按以下方式使用它:
asm(
"number: \n"
".long 0xFFFFFFFF \n
);
extern int number;
int main(){
//do something with number
}
现在我想在汇编程序中声明一个 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
}
我不太了解汇编程序,但我必须使用这个特定变量。
你的内联汇编器做这个
asm(
"number: \n"
".long 0xFFFFFFFF \n"
[snip rest of array]
);
然后你告诉 C number 是
extern unsigned char* number;
这表示 number 是一个指向无符号字符的指针。然后你像这样访问它:
printf("%x ", number[0]);
这表示 de-reference number 中的指针和 return 第一个字符。这与做的一样:
printf("%x ", *(number+0));
问题是 number 被定义为指针。假设 32 位指针转换为:
*(0xFFFFFFFF+0)
如果出现段错误,可能是因为您的程序无法访问地址 0xFFFFFFFF。
您可以将 extern 语句更改为:
extern unsigned char number[32];
现在 number 是一个包含 32 个无符号字符的数组。我倾向于使用 inttypes.h
header 并将其声明为:
extern uint8_t number[32];
uint8_t
保证为 8 位(或 1 字节)。另一方面,char
被定义为至少 8 位(但可以更多)。但是 sizeof(char)
将始终 return 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
关键字(除非被 -fasm
覆盖)当使用 -std=c99
选项时。
number 可能不是无符号字符数组的好名称。当必须有人来维护您的代码时,这可能会造成混乱。
我在汇编程序中声明了一个整数,我在 C 中按以下方式使用它:
asm(
"number: \n"
".long 0xFFFFFFFF \n
);
extern int number;
int main(){
//do something with number
}
现在我想在汇编程序中声明一个 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
}
我不太了解汇编程序,但我必须使用这个特定变量。
你的内联汇编器做这个
asm(
"number: \n"
".long 0xFFFFFFFF \n"
[snip rest of array]
);
然后你告诉 C number 是
extern unsigned char* number;
这表示 number 是一个指向无符号字符的指针。然后你像这样访问它:
printf("%x ", number[0]);
这表示 de-reference number 中的指针和 return 第一个字符。这与做的一样:
printf("%x ", *(number+0));
问题是 number 被定义为指针。假设 32 位指针转换为:
*(0xFFFFFFFF+0)
如果出现段错误,可能是因为您的程序无法访问地址 0xFFFFFFFF。
您可以将 extern 语句更改为:
extern unsigned char number[32];
现在 number 是一个包含 32 个无符号字符的数组。我倾向于使用 inttypes.h
header 并将其声明为:
extern uint8_t number[32];
uint8_t
保证为 8 位(或 1 字节)。另一方面,char
被定义为至少 8 位(但可以更多)。但是 sizeof(char)
将始终 return 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
关键字(除非被 -fasm
覆盖)当使用 -std=c99
选项时。
number 可能不是无符号字符数组的好名称。当必须有人来维护您的代码时,这可能会造成混乱。