Как открыть файл на ассемблере и изменить его? - PullRequest
3 голосов
/ 29 ноября 2011

Я начинаю изучать Ассемблер и работаю в 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 ]

16 голосов
/ 29 ноября 2011

Это 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

2 - это флаг O_RDWR для системного вызова open. Если вы хотите, чтобы файл был создан, если он еще не существует, вам также понадобится флаг O_CREAT; и если вы укажете O_CREAT, вам понадобится третий аргумент, который является режимом разрешений для файла. Если вы покопаетесь в заголовках C, вы обнаружите, что O_CREAT определяется как 0100 - остерегайтесь начального нуля: это восьмеричная константа! Вы можете написать восьмеричные константы в nasm, используя суффикс o.

Так что вам нужно что-то вроде mov ecx, 0102o, чтобы получить правильные флаги и mov edx, 0666o, чтобы установить разрешения.

int 80h

Код возврата из системного вызова передается в eax. Здесь это будет дескриптор файла (если открытие было успешным) или небольшое отрицательное число, которое является отрицательным кодом errno (например, -1 для EPERM). Обратите внимание, что соглашение для возврата кодов ошибок из необработанного системного вызова - , а не , в точности то же самое, что и для оболочек системного вызова C (которые обычно возвращают -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
0 голосов
/ 26 марта 2019

Это пример Linux для x64

; 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

0 голосов
/ 29 ноября 2011

Читали ли вы Linux Assembly HOWTO ?Он охватывает ваш вопрос.

Вы также можете скомпилировать код C с помощью gcc -S -fverbose-asm -O1 и посмотреть на сгенерированную сборку.

Наконец, я не думаю, что стоит много беспокоиться оассемблер.Компилятор наверняка сгенерирует лучший код, чем тот, который вы могли бы написать.

0 голосов
/ 29 ноября 2011

Это зависит от того, какой ассемблер вы используете, и ожидаете ли вы использовать среду выполнения C или нет. В этом случае, который является примером текста Hello World из rosettacode , они используют 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 относится к открытому потоку ввода / вывода. В вашем случае стандартный вывод.

...