Linux bootc.c中的GCC内联程序集:汇编程序消息:错误:junk';int 0x10h';表达后

Linux bootc.c中的GCC内联程序集:汇编程序消息:错误:junk';int 0x10h';表达后,gcc,assembly,Gcc,Assembly,我正试图通过gcc编译c文件并获得 错误 代码 GCC中的内联程序集是正常的字符串,遵循C或C++中的常规规则(无论您在编程中)。 这意味着相邻的文本字符串之间只有空格或注释,它们将被连接成单个字符串 你认为是什么 asm( "mov %al, 'H'" "int 0x10h" ); 从编译器的角度来看 asm( "mov %al, 'H' int 0x10h" ); 上述说明无效 这就是为什么,如果您查看许多GCC内联汇编的示例,那么在每一条装配线之后都需要换行。

我正试图通过gcc编译c文件并获得 错误

代码


GCC中的内联程序集是正常的字符串,遵循C或C++中的常规规则(无论您在编程中)。 这意味着相邻的文本字符串之间只有空格或注释,它们将被连接成单个字符串

你认为是什么

asm(
    "mov %al, 'H'"
    "int 0x10h"
);
从编译器的角度来看

asm(
    "mov %al, 'H' int 0x10h"
);
上述说明无效

这就是为什么,如果您查看许多GCC内联汇编的示例,那么在每一条装配线之后都需要换行。如

// also converted to Extended Asm syntax to fix other problems
asm(
    "mov $'H', %%al\n"  // Note newline here at the end
    "int $0x10"        // gas doesn't understand trailing-h suffix, only 0x for hex
    : // no outputs
    : // no inputs
    : "ax"  // tell the compiler we clobber AX
     // FIXME: also tell the compiler about any other registers this uses
);
文字字符串仍将被连接,但现在在指令之间有一个换行符供汇编程序区分它们。使用
\n\t
是很常见的,这样编译器的asm输出就可以正常读取和缩进


另一方面,您确实应该了解更多,因为您的代码还存在其他问题。例如,汇编代码中的数字文本需要加上前缀
$
;十六进制数字没有十六进制后缀,只有普通的
0x
前缀(同时使用前缀和后缀
h
是多余的)

还请注意,AT&T语法的destination last,因此使用
mov$'H',%AL
将立即值
'H'
移动到AL中


不要忘了根据设置AH为函数代码。编译器可以做任何它想要的任何事情,A/.P>> P>在GCC中的内联程序集是正常的文字字符串,遵循C或C++中的常规规则(无论你在编程什么)。 这意味着相邻的文本字符串之间只有空格或注释,它们将被连接成单个字符串

你认为是什么

asm(
    "mov %al, 'H'"
    "int 0x10h"
);
从编译器的角度来看

asm(
    "mov %al, 'H' int 0x10h"
);
上述说明无效

这就是为什么,如果您查看许多GCC内联汇编的示例,那么在每一条装配线之后都需要换行。如

// also converted to Extended Asm syntax to fix other problems
asm(
    "mov $'H', %%al\n"  // Note newline here at the end
    "int $0x10"        // gas doesn't understand trailing-h suffix, only 0x for hex
    : // no outputs
    : // no inputs
    : "ax"  // tell the compiler we clobber AX
     // FIXME: also tell the compiler about any other registers this uses
);
文字字符串仍将被连接,但现在在指令之间有一个换行符供汇编程序区分它们。使用
\n\t
是很常见的,这样编译器的asm输出就可以正常读取和缩进


另一方面,您确实应该了解更多,因为您的代码还存在其他问题。例如,汇编代码中的数字文本需要加上前缀
$
;十六进制数字没有十六进制后缀,只有普通的
0x
前缀(同时使用前缀和后缀
h
是多余的)

还请注意,AT&T语法的destination last,因此使用
mov$'H',%AL
将立即值
'H'
移动到AL中


不要忘了根据设置AH为函数代码。编译器可以用AH做任何它想做的事情。

在提供的答案之上:除非此代码在实模式下运行,或者在VM8086任务中,否则它将无法工作。BIOS中断调用在32位保护模式下不可用。您可以考虑像布鲁斯的C编译器(<代码> BCC < /代码>)或Alexy Frunzes Smaller C编译器那样的编译器,它可以正确地处理16位代码。将GCC用于16位代码是有问题的。此处可以找到使用GCC的两阶段引导加载程序的示例:。它是概念验证,非常混乱,如果您不知道自己在做什么,则不建议使用它。如果您很勇敢,并且希望使用GCC编写16位代码,这里有GCC-ia16项目:。我个人没有使用过它,也不能保证它的有用性或者它是否有缺陷。除了提供的答案之外:除非此代码在实模式下运行,或者在VM8086任务中,否则它不会工作。BIOS中断调用在32位保护模式下不可用。您可以考虑像布鲁斯的C编译器(<代码> BCC < /代码>)或Alexy Frunzes Smaller C编译器那样的编译器,它可以正确地处理16位代码。将GCC用于16位代码是有问题的。此处可以找到使用GCC的两阶段引导加载程序的示例:。它是概念验证,非常混乱,如果您不知道自己在做什么,则不建议使用它。如果您很勇敢,并且希望使用GCC编写16位代码,这里有GCC-ia16项目:。我个人没有使用过它,也不能保证它的有用性或它是否有缺陷。@PeterCordes:如果在这个扩展内联程序集中,它应该是
%%al
case@MichaelPetch:接得好,固定好了。呃,很难在同一个语句中回答多个问题,但我真的认为这是一个更好的答案,如果它不仅编译,而且还汇编,并且在不告诉编译器的情况下不破坏寄存器。但是,正如您在问题上所评论的那样,来自gcc编译代码的
int$0x10
可能并不好。而且肯定不是使用
-m32
,所以这是另一个没有真正解决的问题。除了杜德先生所说的,OP还应该习惯使用-s来查看生成的实际汇编程序输出。当传递输入和输出约束时,这一点尤为重要。@PeterCordes:如果在本例的扩展内联程序集中,则它应该是
%%al
case@MichaelPetch:接得好,固定好了。呃,很难在同一个语句中回答多个问题,但我真的认为这是一个更好的答案,如果它不仅编译,而且还汇编,并且在不告诉编译器的情况下不破坏寄存器。但是,正如您在问题上所评论的那样,来自gcc编译代码的
int$0x10
可能并不好。而且肯定不是使用
-m32
,所以这是另一个没有真正解决的问题。除了杜德先生所说的,OP还应该习惯使用-s来查看生成的实际汇编程序输出。当传递输入和输出约束时,这可能变得特别重要。