-2

我正在尝试在 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; 
}

我能得到一些帮助吗?

4

2 回答 2

2

理论上,只有使用 DJGPP(DOS 的 gcc 端口)编译的程序才能通过 DOS 扩展程序合法地使用 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 应用程序中不起作用。时期。你有错误的教程。

于 2012-09-02T02:13:41.747 回答
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并恢复正确的数据段。

于 2012-09-18T13:11:49.100 回答