c - 如何使用内联汇编 (NASM) 进行文件 I/O

标签 c assembly inline-assembly

我尝试使用内联 NASM 在 stdout 中编写一个 char[](注意添加了 .intel_syntax 和 .att_syntax,以便可以使用 gcc 进行编译)

但它不会在标准输出中写入任何内容。

我在虚拟机上使用 Linux 16 (x86)

是 char c[] 的原因吗? (我通过这种编译方式读到我们不能使用内存变量,但是该怎么办呢?)

#include<stdio.h>


char c[] = "abcd";

int main(){
    asm (".intel_syntax noprefix");

    // write c into stdout
    asm("mov EAX,4"); // 4: write
    asm("mov EBX,1"); // 1: stdout
    asm("mov ECX,c");
    asm("mov EDX,5");
    asm("int 0x80");

    // exit program
    asm("mov EAX,1")
    asm("int 0x80")

    asm (".att_syntax noprefix");
}

没有输出

最佳答案

GNU 汇编器(gcc 使用的)不使用 NASM 语法。它而是使用 Microsoft 的 MASM 语法的变体,其中不需要括号来取消引用变量。由于您不想加载 c 变量的值而是它的地址,因此您需要一个 offset 关键字:

mov ecx, offset c

我强烈建议您在学习汇编时尽可能避免使用内联汇编。在 gcc 中使用内联汇编需要很好地了解整个事情的具体工作原理,并且编写随机指令通常会导致错误代码。即使您的简单代码已经从根本上被破坏,如果它比这更复杂也将无法工作(因此编译器有机会尝试使用您覆盖的寄存器而不告诉)。

相反,将您的程序集放在一个单独的文件中并将其链接进去。这样可以避免您使用内联程序集时遇到的所有问题,并允许您根据需要使用 NASM。例如,尝试这样的事情:

主.c

char c[] = "abcd";

/* the function you define in print_c.asm */
extern void print_c();

int main() {
    print_c(); /* call your assembly function */
}

打印_c.asm

    ; pull in c defined in main.c
    extern c

    section .text

    global print_c

print_c:
    ; write c to stdout
    mov eax, 4
    mov ebx, 1
    mov ecx, c
    mov edx, 5
    int 0x80

    ; exit program
    mov eax, 1
    int 0x80

然后组装、编译并链接:

nasm -felf print_c.asm
cc -m32 -o print_c print_c.o main.c

关于c - 如何使用内联汇编 (NASM) 进行文件 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53922693/

相关文章:

java - 将指向结构体 (StructureByReference) 的指针传递到 C 代码中,如何再次访问该数据?

c - 我怎么知道编译器是否会优化一个变量?

assembly - x86 操作码编码中的方向/符号扩展位

c - 与 SSE 的 128 位哈希比较

c - 为什么 MapViewOfFile 返回一个无法使用的 RapidXML 指针?

c - 使用数组 [C] 计数时的无限循环

assembly - 如何运行 linaro 汇编程序以获取 thumb2 (T32) 指令

c++ - 使用 gcc 编译内联汇编时出错, "shl"

c++ - 内联以汇编语言编写的外部函数

x86 - 当我从内联汇编中调用 C++ 函数时,如何将参数传递给它们