如何在汇编程序中打开文件并进行修改?

时间:2011-11-29 14:20:17

标签: linux assembly x86 nasm

我开始学习汇编程序,我在Unix工作。我想打开一个文件并在上面写上“Hello world”。

section.data

textoutput db 'Hello world!', 10
lentext equ $ - textoutput
filetoopen db 'hi.txt'

section .text
global _start

_start:

mov eax, 5            ;open
mov ebx, filetoopen
mov ecx, 2            ;read and write mode
int 80h

mov eax, 4
mov ebx, filetoopen   ;I'm not sure what do i have to put here, what is the "file descriptor"?
mov ecx, textoutput
mov edx, lentext

mov eax, 1
mov ebx, 0
int 80h              ; finish without errors

但是当我编译它时,它什么也没做。我究竟做错了什么? 当我打开一个文件,文件描述符值返回哪里?

4 个答案:

答案 0 :(得分:15)

这是x86 Linux(x86不是唯一的汇编语言,Linux不是唯一的Unix!)...

section .data

textoutput db 'Hello world!', 10
lentext equ $ - textoutput
filetoopen db 'hi.txt'

文件名字符串需要一个0字节的终结符:filetoopen db 'hi.txt', 0

section .text
global _start

_start:

mov eax, 5            ;open
mov ebx, filetoopen
mov ecx, 2            ;read and write mode

2O_RDWR系统调用的open标志。如果您希望创建该文件(如果该文件尚不存在),您还需要O_CREAT标志;如果指定O_CREAT,则需要第三个参数,即文件的权限模式。如果你在C标题中徘徊,你会发现O_CREAT定义为0100 - 小心前导零:这是一个八进制常量!您可以使用nasm后缀在o中编写八进制常量。

所以你需要像mov ecx, 0102o这样的东西来获得正确的旗帜,mov edx, 0666o来设置这些权利。

int 80h

来自系统调用的返回码在eax中传递。这里,这将是文件描述符(如果打开成功)或小负数,这是一个负errno代码(例如,EPERM为-1)。请注意,从原始系统调用返回错误代码的约定 not 与C syscall包装器完全相同(通常返回-1并设置errno误差)...

mov eax, 4
mov ebx, filetoopen   ;I'm not sure what do i have to put here, what is the "file descriptor"?

...所以在这里你需要mov ebx, eax首先(在覆盖open之前保存eax结果)然后mov eax, 4。 (您可能想要先考虑检查结果是否为正,如果不是,则考虑以某种方式打开失败。)

mov ecx, textoutput
mov edx, lentext

此处缺少int 80h

mov eax, 1
mov ebx, 0
int 80h              ; finish without errors

答案 1 :(得分:0)

这取决于您使用的汇编程序以及您是否希望使用C运行时。在这种情况下,似乎是来自rosettacode的Hello World文本示例,他们正在使用nasm。假设您有一个_start字段,则不需要C运行时,因此您将其组合到一个elf对象文件并将其链接到一个程序中:

nasm -felf hello.asm
ld hello.o -o hello

现在您可以运行hello程序。

使用C运行时执行工作而不是linux系统调用的稍微可移植的示例可能如下所示。如果您按照描述进行链接,则可以使用printf进行打印。

;;; helloworld.asm -
;;;
;;; NASM code for Windows using the C runtime library
;;;
;;; For windows - change printf to _printf and then:
;;;   nasm -fwin32 helloworld.asm
;;;   link -subsystem:console -out:helloworld.exe -nodefaultlib -entry:main
;;;       helloworld.obj msvcrt.lib
;;; For gcc (linux, unix etc):
;;;   nasm -felf helloworld.asm
;;;   gcc -o helloworld helloworld.o

        extern printf

        section .data
message:
        db 'Hello, World', 10, 0

        section .text
        global main
main:
        push    dword message   ; push function parameters
        call    printf          ; call C library function
        add     esp, 4          ; clean up the stack
        mov     eax, 0          ; exit code 0
        ret

有关文件描述符的信息 - 请阅读open(2)手册页或查看wikipedia。 posix是指一个开放的i / o流。在你的情况下,stdout。

答案 2 :(得分:0)

你读过Linux Assembly HOWTO了吗?它涵盖了你的问题。

您还可以使用gcc -S -fverbose-asm -O1编译一些C代码并查看生成的程序集。

最后,我认为不值得为汇编程序打扰。编译器肯定会产生比你写的更好的代码。

答案 3 :(得分:0)

这是x64 Linux示例

; Program to open and write to file
; Compile with:
;     nasm -f elf64 -o writeToFile64.o writeToFile64.asm
; Link with:
;     ld -m elf_x86_64 -o writeToFile64 writeToFile64.o
; Run with:
;     ./writeToFile64
;==============================================================================
; Author : Rommel Samanez
;==============================================================================
global _start

%include 'basicFunctions.asm'

section .data
  fileName:  db "testFile.txt",0
  fileFlags: dq 0102o         ; create file + read and write mode
  fileMode:  dq 00600o        ; user has read write permission
  fileDescriptor: dq 0
section .rodata    ; read only data section
  msg1: db "Write this message to the test File.",0ah,0
  msglen equ $ - msg1
  msg2: db "File Descriptor=",0

section .text
_start:
    mov rax,2               ;   sys_open
    mov rdi,fileName        ;   const char *filename
    mov rsi,[fileFlags]       ;   int flags
    mov rdx,[fileMode]        ;   int mode
    syscall
    mov [fileDescriptor],rax
    mov rsi,msg2
    call print
    mov rax,[fileDescriptor]
    call printnumber
    call printnewline
    ; write a message to the created file
    mov rax,1                 ; sys_write
    mov rdi,[fileDescriptor]
    mov rsi,msg1
    mov rdx,msglen
    syscall
    ; close file Descriptor
    mov rax,3                 ; sys_close
    mov rdi,[fileDescriptor]
    syscall


    call exit