【问题标题】:How to run converted .asm code from .c using 'gcc' in Emu8086如何在 Emu8086 中使用“gcc”从 .c 运行转换后的 .asm 代码
【发布时间】:2019-04-29 09:45:46
【问题描述】:

我是新来的,我将代码从 C 语言转换为 asm。但是,它看起来不像 asm 语言中的普通代码。所以我的问题是如何将代码从 C(或 C++)语言转换为汇编语言,转换后的 asm 代码可以在 Emu8086 上运行。

这是一个简单的c代码:

#include<stdio.h>

void Hello(){
printf("Hello world");
}
int main (){
Hello();
return 0;
}

然后我用gcc -S test.c 转换它,这是答案:

.file   "test1.c"
    .section    .rodata
.LC0:
    .string "Hello world"
    .text
    .globl  Hello
    .type   Hello, @function
Hello:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    leaq    .LC0(%rip), %rdi
    movl    $0, %eax
    call    printf@PLT
    nop
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   Hello, .-Hello
    .globl  main
    .type   main, @function
main:
.LFB1:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $0, %eax
    call    Hello
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1:
    .size   main, .-main
    .ident  "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
    .section    .note.GNU-stack,"",@progbits

【问题讨论】:

  • 那是 64 位代码。你永远不会在emu8086中运行它。您可以使用 16 位编译器,但即便如此,您也没有标准库,因此您应该避免使用诸如 printf 之类的函数。当然,实际的汇编语法也可能需要调整。但是,您可以在 gdb 中本地运行它(取决于您想要实现的目标)。
  • 那行不通..不仅因为语法不同,还因为您确实使用了 64 位 gcc(针对 x86-64 模式),这就像不同的 CPU。虽然每个现代 x86 CPU 可以处理三种主要的不同模式(16 位实模式、32 位模式和 64 位模式),但它们有点像三种不同的机器,当你想运行特定的目标时,你必须切换它模式。 emu8086 只模拟 16 位实模式(虽然我认为扩展了 32 位寄存器,如 80386 CPU),但它不能运行 32 位或 64 位模式代码。您将需要用于“x86-16”的 C 编译器,例如 watcom/etc。
  • “我将代码从 C 语言转换为 asm” - 不,你没有。编译器做到了。您刚刚调用了编译器。不同之处就像您服用了阿司匹林药片,然后突然声称您发明了一种治疗方法……可悲的是,这需要更多的努力。

标签: c gcc assembly emu8086 converters


【解决方案1】:

Emu8086 就像它在锡上所说的那样:它模拟 Intel 8086 处理器。 GCC 生成的程序集适用于您的主机(因为您没有告诉它这样做),它显然使用 x86-64 指令集。 8086 无法理解这些指令中的大部分。您需要将其交叉编译为 x86 16 位实模式可执行文件。 GCC 上的-m16 选项将生成 16 位代码,但它显然仍使用 32 位寄存器(EAX 等)。所以你必须找到一个以基本 8086 指令集为目标的编译器。

【讨论】:

  • 无论选项如何,GCC 都不支持 8086。-m16 选项生成使用 32 位寄存器的代码。
  • 不仅指令集错误,而且输出也是针对 GNU as(因此,AT&T 语法和所有以点开头的指令)并针对具有 glibc 的 Linux 机器(@987654323 @,那个特定的调用约定)。
  • 就 AT&T 与 Intel 的语法而言,这应该不是问题,它仍然会汇编成相同的机器代码。而且-masm=intel 无论如何都可以修复它。
猜你喜欢
  • 1970-01-01
  • 2020-04-29
  • 1970-01-01
  • 2013-10-25
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
相关资源
最近更新 更多