AT& T内联C ++ hello world错误

时间:2012-09-01 06:22:23

标签: c++ assembly x86 g++ inline-assembly

我正在尝试在C ++(Dev-CPP)中使用Assembly,它不会按原样输出字符串。经过一些研究后,我发现它使用了AT& T语法。我的代码不会输出它只是出现汇编消息的字符串。 这是我的代码:

#include <iostream>

using namespace std;

int main()
{
    asm(".section .data");
    asm("hello: .string\"Hello, World!$\"\n");
    asm(".section .text");
    asm("movl $0x09, %ah \n");
    asm("mov hello, %dx\n");
    asm("int 0x21");

    system("PAUSE"); 
    return 0; 
}
我可以得到一些帮助。

2 个答案:

答案 0 :(得分:2)

理论上,只有使用DJGPP(用于DOS的gcc端口)编译的程序才能通过DOS扩展器IFF合法地使用DOS服务功能,您可以在DOS或Windows(XP及以下版本,通常不是Vista / 7/8)中运行它们。此外,gcc不会生成16位x86代码,这正是您所期待的。

此外,你应该真的,真正学习一些内联汇编(google it up)。

如果您的代码看起来像可编译的版本:

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
    asm(".section .data");
    asm("hello: .string\"Hello, World!$\"\n");
    asm(".section .text");
    asm("movb $0x09, %ah\n"); // movl->movb
    asm("movl $hello, %edx\n"); // mov->movl,hello->$hello,dx->edx
    asm("int $0x21"); // 0x21->$0x21

    system("PAUSE"); 
    return 0; 
}

但它仍然不太可能是良好的内联汇编,因为:

  • 您的代码会破坏寄存器并且不会告诉编译器哪些是被破坏的,因此它可能会破坏程序的状态,从而导致崩溃或挂起。
  • 您可以在各个asm语句中编写指令,编译器可以在这些语句之间插入任何类型的代码并中断内联汇编。你真的想把你的相关指令放在一个块中,以防止这种情况发生。

这样的事情会更好:

asm volatile (
  ".section .data\n"
  "hello: .string \"Hello, World!$\"\n"
  ".section .text\n"
  "movb $0x09, %ah\n"
  "movl $hello, %edx\n"
  "int $0x21\n"
);

不幸的是,即使使用DJGPP,这仍然无效。这个问题与DJGPP和DPMI主机(CWSDPMI)完成的内存分段设置有关,可能是虚拟内存。我不知道那里究竟出了什么问题,但上面的代码并没有按原样运作。

所以,请弄清楚你正在为你的程序编译什么操作系统,并为该操作系统适当地编写内联汇编代码,即使用正确的寄存器和系统调用机制。

DOS int 21h函数在本机Windows和Linux应用程序中不起作用。期。你的教程错了。

答案 1 :(得分:0)

要扩展Alexey的答案(如何克服分段问题),这将编译(并可能在DOS上运行):

asm volatile(
    "call 0f\n"
    ".byte 'H','e','l','l','o','W','o','r','l','d','!',0\n"
    "0: pop %0\n"
    "push %ds\n"
    "push %cs\n"
    "pop %ds\n"
    "int $0x21\n"
    "pop %ds\n" : "d"(0), "a"(9) : : "memory", "cc");

这个想法是在代码中内联字符串,但跳过它;该调用的返回地址是字符串的起始地址。然后暂时使数据段与代码段相同,调用DOS INT并在此之后恢复正确的数据段。