2014-11-15 1 views
-2

Мне нужно создать программу, которая выводит текстовый файл с расширением .dna, я не знаю, смогу ли я это сделать, и если текстовый файл будет даже совместим с тем, что мне нужно сравнить после этого. Во всяком случае, я не совсем уверен, как это сделать. Я попытался найти несколько примеров для NASM, но я не нашел много. У меня есть представление о том, что мне нужно делать, но я просто не знаю, что вызывать для создания файла.Есть ли примеры программ, которые генерируют текстовые текстовые файлы как выходные данные в NASM?

Впоследствии мне нужно было написать в него материал, я не уверен, как это сделать. Может ли кто-нибудь указать мне на некоторые примеры или что-то еще? Мне просто нужно посмотреть, что нужно, чтобы написать свою собственную вещь.

+1

32 или 64 бит? Кроме того, готовы ли вы использовать библиотеку C или только системные вызовы ядра? –

+0

32 бит, и да, я могу использовать библиотеки. – Argus

+0

Затем просто подключитесь к libc и используйте стандартные функции C. Кроме того, обычно нет смысла использовать ввод-вывод файлов из сборки, возможно, вы можете использовать C и просто написать некоторые части в asm. – Jester

ответ

1

Вот пример использования системных вызовов. В принципе, вы просто открыть файл, запись данных в нее, затем закрыть и выход:

; 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, если вы скопировали мою команду ссылку выше. Опция -o для ld меняет это.

Мы также можем вызвать функции 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 основной() в сборке. Но вы должны начать писать текстовый файл. Совет. Файлы такие же, как и запись на экран, вам просто нужно сначала открыть/создать их!

BTW не смешивает системные вызовы и функции библиотеки C одновременно. Библиотека C (fprintf и т. Д.) Буферизует данные, системных вызовов нет. Если вы их смешиваете, данные могут быть записаны в файл в удивительном порядке.

Код аналогичный, но немного другой в 64 бит.

И, наконец, этот же шаблон можно использовать для перевода почти любого кода C в asm. Соглашение о вызове C одинаково с различными функциями, а соглашение с системным вызовом Linux с размещением аргументов и т. Д. Также следует за последовательным шаблоном.

Дальнейшее чтение: http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl на C вызовах

http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html по системе Linux называет

What is the purpose of EBP in the following code? это еще один SO ответ я написал некоторое время назад о локальных переменных в ассемблере - это будет иметь намеки на один способ избавиться от этого глобального и описать, как это делает компиляция C. (другой способ избавиться от этого глобального - либо сохранить fd/fp в регистре, либо нажать и поместить его в стек, когда вам нужно освободить регистр для чего-то еще)

И ссылки на страницы руководства в коде для каждой функции. Из командной строки linux сделайте что-нибудь вроде man 2 write или man 3 fprintf, чтобы увидеть больше. (Системные вызовы находятся в ручном разделе 2, а функции C находятся в ручном разделе 3).

+0

Спасибо, это сработает для меня. – Argus

Смежные вопросы