flat assembler
Message board for the users of flat assembler.

Index > Windows > outputing to a text file

Author
Thread Post new topic Reply to topic
tthsqe



Joined: 20 May 2009
Posts: 730
tthsqe
How can I ouput a bunch of numbers computed in a program to a text file?
The text file should look like
num1, num2, num3, ...
Post 30 Jun 2009, 22:38
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1288
Location: behind the arc
Picnic
Hi, tthsqe.
Format the numbers the way you like to a string buffer and then save it to file.
Search for CreateFile, WriteFile, ReadFile e.t.c,
You'll find many examples inside forum, here is something simple to get you started.

Code:
        format pe console 4.0

        include 'win32ax.inc'

.data
        FileTitle db 'c:\fasm.txt',0
        FileHandle dd ?
        BytesWritten dd ?

.code
main:
        invoke CreateFile, FileTitle, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
        test eax, eax
        je ApiError

        mov [FileHandle], eax

        invoke WriteFile, [FileHandle], FileTitle, 11, BytesWritten, 0
        test eax, eax
        je ApiError

.exit:
        invoke CloseHandle, [FileHandle]
        invoke ExitProcess, 0
.end main



ApiError:
        ; api error routine
        ;
        jmp main.exit
    


Here is one written by shoorick, related to file usage.
Post 30 Jun 2009, 23:19
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
A prime number list generator seriously asking for optimizations:
Code:
MAX_NUMBER = 104729 ; Don't put a very high number here, besides the time required to make up the list, you'll get a stack overflow.
                    ; If curious, I got a stack overflow with a list generated up to the prime number 779327 (62417 prime numbers)

format pe console
include 'win32axp.inc'

start:
      push    ebp
      mov     ebp, esp

      invoke  CreateFile, 'output.txt', GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
      mov     ebx, eax

      mov     eax, 2
      mov     esi, 1
      push    eax
      jmp     .printPrime

align 16
.isPrime:
      lea     edi, [ebp - 4]
      add     esi, 2
      cmp     esi, MAX_NUMBER
      jbe     .isTableProcessed

      jmp     .done

  align 16
  .checkPrimality:
        mov     ecx, [edi]
        sub     edi, 4

        xor     edx, edx
        mov     eax, esi
        div     ecx

        test    edx, edx
        jz      .isPrime

      ; This code never resulted in better performance even with MAX_NUMBER = 104729*8 with an AMD Athlon64 Venice
      ;  test    eax, eax
      ;  jz      .itIsPrime

  .isTableProcessed:
        cmp     edi, esp
        jae     .checkPrimality

.itIsPrime:
      push    esi
      mov     eax, esi

.printPrime:
      mov     ecx, separator
      mov     edi, 10

  .intToStr:
        dec     ecx
        xor     edx, edx
        div     edi
        add     dl, '0'
        mov     [ecx], dl

        test    eax, eax
        jnz     .intToStr


      mov     eax, separator + sizeof.separator
      sub     eax, ecx
      invoke  WriteFile, ebx, ecx, eax, numberOfBytesWritten, NULL

      jmp     .isPrime

.done:
      leave
      invoke  CloseHandle, ebx
      invoke  ExitProcess, 0


strBuffer rb 10
separator db 13, 10
sizeof.separator = $ - separator


numberOfBytesWritten rd 1

.end start    


[edit] Changed the code a bit to make it substantially faster (~3x faster).
[edit2] Corrected a label's name since there is no sieve here.


Last edited by LocoDelAssembly on 01 Jul 2009, 04:02; edited 2 times in total
Post 01 Jul 2009, 00:42
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 730
tthsqe
That did work, but I still have some questions:
How do you do it for 64-bit programs?
Where do you actually code the contents of the file in the program? (a buffer, maybe?)
Could I append strings to the file one by one, instead of writing it all at once?
Post 01 Jul 2009, 00:54
View user's profile Send private message Reply with quote
eskizo



Joined: 22 Nov 2005
Posts: 59
eskizo
Code:
push    ebp
mov     ebp, esp 
    


why to do this?
Post 01 Jul 2009, 02:00
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
Because the entry point is not a leaf function so to do this in "the right way", I use that prologue sequence, and before calling ExitProcess I execute leave. If you remove "push ebp" and "leave", and change "lea edi, [ebp-4]" with "mov edi, ebp", the code will work OK too, but just to be safe I better leave the code as it is now.
Post 01 Jul 2009, 02:11
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 2937
Location: vpcmipstrm
bitRAKE
tthsqe wrote:
That did work, but I still have some questions:
How do you do it for 64-bit programs? Where do you actually code the contents of the file in the program? (a buffer, maybe?) Could I append strings to the file one by one, instead of writing it all at once?
An easy way is to memory map the maximum size needed then just write to memory and let the OS do the shuffling of data to disk. A more flexible way is to just map a few pages of the file, and shift the map as needed.

_________________
¯\(°_o)/¯ unlicense.org
Post 01 Jul 2009, 04:04
View user's profile Send private message Visit poster's website Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 730
tthsqe
ok, I guess I'll have to be more specific.
Could someone show me the 64-bit code to create a file with
1) a given file name
2) contents given by the null-terminated character string starting at a given memory location
Post 01 Jul 2009, 05:13
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 730
tthsqe
a text file that is
Post 01 Jul 2009, 05:15
View user's profile Send private message Reply with quote
Picnic



Joined: 05 May 2007
Posts: 1288
Location: behind the arc
Picnic
LocoDelAssembly wrote:
Because the entry point is not a leaf function so to do this in "the right way", I use that prologue sequence, and before calling ExitProcess I execute leave. If you remove "push ebp" and "leave", and change "lea edi, [ebp-4]" with "mov edi, ebp", the code will work OK too, but just to be safe I better leave the code as it is now.

So, LocoDelAssembly leave instruction is same like writing... (?)
Code:
mov   esp, ebp      
pop   ebp            
    


Sorry to ask here tthsqe.
p.s unfortunately i don't have a 64-Bit machine.
Post 01 Jul 2009, 09:38
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4633
Location: Argentina
LocoDelAssembly
thimis, yes.

tthsqe, I don't have a 64-bit OS to prepare the example correctly for you but the difference is not really big, and if you continue to use "invoke" then you won't have to worry about the calling convention used in Win64.
Post 01 Jul 2009, 14:52
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 730
tthsqe
Ok, it seems that this is doing what I wanted:

Code:
format PE64 GUI
entry start

include 'win64a.inc'

section '.text' code readable executable

start:  invoke CreateFile,FileTitle,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
        test   rax,rax
        je     exit
        mov    [FileHandle], rax
        invoke WriteFile,[FileHandle],FileContent,17,BytesWritten,0
exit:   invoke CloseHandle,[FileHandle]
        invoke ExitProcess,0

section '.data' data readable writeable

  FileTitle db 'C:\Users\---\Documents\itworked.txt',0
  FileHandle dq ?
  BytesWritten dq ?
  FileContent  db 'It really worked!',0

section '.idata' import data readable writeable
  library kernel32,'KERNEL32.DLL',\
          user32,'USER32.DLL'

  include 'api\kernel32.inc'
  include 'api\user32.inc'    


Now I'm wondering what the arguments on invoke WriteFile actually do. It looks like the 17 indicates that the first 17 bytes of the character string get written. But then what is the point of the last two arguments - BytesWritten and 0? Also, CreateFile seems to be returning with 0x10 in rax. How is this related to the actual location of the file?
Post 01 Jul 2009, 23:42
View user's profile Send private message Reply with quote
arigity



Joined: 22 Dec 2008
Posts: 45
arigity
tthsqe wrote:

Now I'm wondering what the arguments on invoke WriteFile actually do. It looks like the 17 indicates that the first 17 bytes of the character string get written. But then what is the point of the last two arguments - BytesWritten and 0? Also, CreateFile seems to be returning with 0x10 in rax. How is this related to the actual location of the file?


you should see msdn for what function arguments/return values are for.
Post 01 Jul 2009, 23:56
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 730
tthsqe
Thanks
Post 02 Jul 2009, 02:01
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on YouTube, Twitter.

Website powered by rwasa.