如何使用内联程序集(NASM)进行文件I / O

时间:2018-12-25 13:12:36

标签: c assembly inline-assembly

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

但它不会在stdout中写入任何内容。

我正在虚拟机上使用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");
}

输出为空

1 个答案:

答案 0 :(得分:3)

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

mov ecx, offset c

我强烈建议您在学习汇编时尽可能避免内联汇编。在gcc中使用内联汇编需要充分了解整个程序的工作原理,编写随机指令通常会导致错误的代码。甚至您的简单代码都已经从根本上被破坏了,甚至比它更复杂也无法正常工作(因此,编译器有机会尝试使用您重写的寄存器而无需告知)。

相反,将程序集放在一个单独的文件中并进行链接。这避免了内联程序集的所有问题,并允许您根据需要使用NASM。例如,尝试以下操作:

main.c

char c[] = "abcd";

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

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

print_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