Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 有没有在NASM中生成文本文件作为输出的程序示例?_Linux_Assembly_X86_Nasm - Fatal编程技术网

Linux 有没有在NASM中生成文本文件作为输出的程序示例?

Linux 有没有在NASM中生成文本文件作为输出的程序示例?,linux,assembly,x86,nasm,Linux,Assembly,X86,Nasm,我需要制作一个程序,输出一个扩展名为.dna的文本文件,我不知道我是否真的能做到这一点,而且这个文本文件是否与我以后需要比较的文件兼容。不管怎样,我真的不知道怎么做。我试图为NASM寻找一些例子,但没有找到太多。我知道我需要做什么,但我不知道调用什么来生成文件 之后我需要在里面写些东西,我真的不知道该怎么做。有人能给我举一些例子吗?我只需要看看写我自己的东西需要什么。下面是一个使用系统调用的示例。基本上,您只需打开文件,向其中写入一些数据,然后关闭并退出: ; nasm -f elf file.

我需要制作一个程序,输出一个扩展名为.dna的文本文件,我不知道我是否真的能做到这一点,而且这个文本文件是否与我以后需要比较的文件兼容。不管怎样,我真的不知道怎么做。我试图为NASM寻找一些例子,但没有找到太多。我知道我需要做什么,但我不知道调用什么来生成文件


之后我需要在里面写些东西,我真的不知道该怎么做。有人能给我举一些例子吗?我只需要看看写我自己的东西需要什么。

下面是一个使用系统调用的示例。基本上,您只需打开文件,向其中写入一些数据,然后关闭并退出:

; nasm -f elf file.asm
; ld -m elf_i386 file.o
BITS 32
section .data
        ; don't forget the 0 terminator if it akes a C string!
        filename: db 'test.txt', 0

        ; an error message to be printed with write(). The function doesn't
        ; use a C string so no need for a 0 here, but we do need length.
        error_message: db 'Something went wrong.', 10 ; 10 == \n
        ; this next line means current location minus the error_message location
        ; which works out the message length.
        ; many of the system calls use pointer+length pairs instead of
        ; 0 terminated strings.
        error_message_length: equ $ - error_message

        ; a message we'll write to our file, same as the error message
        hello: db 'Hello, file!', 10 ; the 10 is a newline at the end
        hello_length: equ $ - hello

        fd: dd 0 ; this is like a global int variable in C
        ; global variables are generally a bad idea and there's other
        ; ways to do it, but for simplicity I'm using one here as the
        ; other ways are a bit more work in asm
section .text
        global _start
_start:
        ; first, open or create the file. in C it would be:
        ; // $ man 2 creat
        ; int fd = creat("file.txt", 0644); // the second argument is permission

        ; we get the syscall numbers from /usr/include/asm/unistd_32.h
        mov eax, 8 ; creat
        mov ebx, filename ; first argument
        mov ecx, 644O ; the suffix O means Octal in nasm, like the leading 0 in C. see: http://www.nasm.us/doc/nasmdoc3.html
        int 80h ; calls the kernel

        cmp eax, -1 ; creat returns -1 on error
        je error

        mov [fd], eax ; the return value is in eax - the file descriptor

        ; now, we'll write something to the file
        ; // man 2 write
        ; write(fd, hello_pointer, hello_length)
        mov eax, 4 ; write
        mov ebx, [fd],
        mov ecx, hello
        mov edx, hello_length
        int 80h

        cmp eax, -1
        ; it should also close the file in a normal program upon write error
        ; since it is open, but meh, since we just terminate the kernel
        ; will clean up after us
        je error

        ; and now we close the file
        ; // man 2 close
        ; close(fd);

        mov eax, 6 ; close
        mov ebx, [fd]
        int 80h

        ; and now close the program by calling exit(0);
        mov eax, 1 ; exit
        mov ebx, 0 ; return value
        int 80h
error:
        mov eax, 4 ; write
        mov ebx, 1 ; write to stdout - file #1
        mov ecx, error_message ; pointer to the string
        mov edx, error_message_length ; length of the string
        int 80h ; print it

        mov eax, 1 ; exit
        mov ebx, 1 ; return value
        int 80h
如果您复制了上面的“我的链接”命令,该文件将被称为
a.out
。ld的
-o
选项会改变这一点

我们还可以调用C函数,如果您需要写出数字之类的内容,这会很有帮助

; nasm -f elf file.asm
; gcc -m32 file.o -nostdlib -lc # notice that we're using gcc to link, makes things a bit easier
; # the options are: -m32, 32 bit, -nostdlib, don't try to use the C lib cuz it will look for main()
; # and finally, -lc to add back some of the C standard library we want
BITS 32

; docs here: http://www.nasm.us/doc/nasmdoc6.html
; we declare the C functions as external symbols. the leading underscore is a C thing.
extern fopen
extern fprintf
extern fclose

section .data
        ; don't forget the 0 terminator if it akes a C string!
        filename: db 'test.txt', 0

        filemode: db 'wt', 0 ; the mode for fopen in C

        format_string: db 'Hello with a number! %d is it.', 10, 0 ; new line and 0 terminator

        ; an error message to be printed with write(). The function doesn't
        ; use a C string so no need for a 0 here, but we do need length.
        error_message: db 'Something went wrong.', 10 ; 10 == \n
        ; this next line means current location minus the error_message location
        ; which works out the message length.
        ; many of the system calls use pointer+length pairs instead of
        ; 0 terminated strings.
        error_message_length: equ $ - error_message

        fp: dd 0 ; this is like a global int variable in C
        ; global variables are generally a bad idea and there's other
        ; ways to do it, but for simplicity I'm using one here as the
        ; other ways are a bit more work in asm
section .text
        global _start
_start:
        ; first, open or create the file. in C it would be:
        ; FILE* fp = fopen("text.txt", "wt");

        ; arguments for C functions are pushed on to the stack, right from left.
        push filemode ; "wt"
        push filename ; "text.txt"
        call fopen
        add esp, 8 ; we need to clean up our own stack. Since we pushed two four-byte items, we need to pop the 8 bytes back off. Alternatively, we could have called pop twice, but a single add instruction keeps our registers cleaner.

        ; the return value is in eax, store it in our fp variable after checking for errors
        ; in C: if(fp == NULL) goto error;
        cmp eax, 0 ; check for null
        je error
        mov [fp], eax;

        ; call fprintf(fp, "format string with %d", 55);
        ; the 55 is just a random number to print

        mov eax, 55
        push eax ; all arguments are pushed, right to left. We want a 4 byte int equal to 55, so eax is it
        push format_string
        mov eax, [fp] ; again using eax as an intermediate to store our 4 bytes as we push to the stack
        push eax
        call fprintf
        add esp, 12 ; 3 words this time to clean up

        ; fclose(fp);
        mov eax, [fp] ; again using eax as an intermediate to store our 4 bytes as we push to the stack
        push eax
        call fclose

        ; the rest is unchanged from the above example

        ; and now close the program by calling exit(0);
        mov eax, 1 ; exit
        mov ebx, 0 ; return value
        int 80h
error:
        mov eax, 4 ; write
        mov ebx, 1 ; write to stdout - file #1
        mov ecx, error_message ; pointer to the string
        mov edx, error_message_length ; length of the string
        int 80h ; print it

        mov eax, 1 ; exit
        mov ebx, 1 ; return value
        int 80h
这里还有很多工作要做,比如一些消除这些全局变量的技术,或者更好的错误检查,甚至在汇编中编写一个C风格的main()。但这应该让你开始写一个文本文件。提示:文件与写入屏幕相同,您只需首先打开/创建它们

顺便说一句,不要同时混合使用系统调用和C库函数。C库(
fprintf
etc)缓冲数据,系统调用不缓冲数据。如果将它们混合使用,数据最终可能会以惊人的顺序写入文件

代码类似,但在64位上略有不同

最后,这个相同的模式可以用于将几乎所有的C代码转换为asm—C调用约定对于不同的函数是相同的,并且带有参数放置等的linux系统调用约定也遵循一致的模式

进一步阅读: 关于C调用约定

关于linux系统调用

这是我不久前写的关于asm中的局部变量的另一个答案——这将提示如何摆脱全局变量,并描述C编译是如何做到这一点的。(另一种摆脱该全局变量的方法是将fd/fp保存在寄存器中,并在需要释放寄存器以进行其他操作时将其推送到堆栈上)


以及代码中为每个函数引用的手册页。在linux提示符下,执行诸如
man2write
man3fprintf
之类的操作以查看更多信息。(系统调用在手动部分2,C函数在手动部分3)。

32位还是64位?另外,你愿意使用C库还是内核系统调用?32位,是的,我可以使用库。然后只需链接到libc并使用标准的C函数。另外,从汇编中使用文件I/O通常没有多大意义,也许您可以使用C,只需在asm中编写一些部件。我甚至不知道如何使用汇编实现这一点。对不起,我的教授是个铅笔推手,我们什么都没看到。他把这个项目扔给了我们,我敢肯定他自己都不知道怎么做。此外,如果我知道怎么做,你真的认为我会问这个吗?我现在写几个例子给你一个想法。。。