Search code examples
assemblymasm

Read/write blocks to file in assembly


I have to write code that is supposed to read the text from a .txt file in 64-byte blocks, encrypt each block and then write it to another .txt file. For now I want to be able to read 64-byte blocks and write them without any change to the destination file. I am aware that there are quite a few problems with my code but I can't figure out how to solve them so any help and suggestions are very much appreciated. Here is what I managed to do.

.386
.model flat, stdcall

includelib msvcrt.lib
extern exit: proc
extern printf: proc
extern scanf: proc
extern fscanf: proc
extern fprintf: proc
extern fopen: proc
extern fclose: proc

public start


.data

  type_read db "r",0

  type_write db "w", 0

  destination db "destination.txt",0      ;name of destination file
  fscanf_format db "%lld",0 
  fprintf_format db "%lld",0

  msg_start db "Source file path:",0

  source dd 0  ;name of source file
  source_format db "%s", 0
  block64 dq 0
  pointer_source db 0
  pointer_destination dd 0

.code

start:
    mov eax,0
    push offset msg_start
    call printf
    add esp,4

    ; read name source file
    push  offset source
    push offset source_format
    call scanf
    add esp,8

    ; open source file
    push offset type_read
    push offset sursa
    call fopen
    add esp,8
    mov pointer_source,eax  ;save source pointer eax

    ; open destination file
    push offset type_write
    push offset destination
    call fopen
    add esp,8
    mov pointer_destination,ebx

    reading:
    ;file reading
    push    offset block64           ;offset of qword variable
    push    offset fscanf_format     ;format string "%lld",0
    push    pointer_source            ;file pointer
    call    fscanf
    add     esp,16

    ;i tried to write what i've read to file destination.txt but i am not sure how to
    pop     ebx
    sub     esp,8

    cmp eax,0ffffffffh;end of file?
    je finish
    end reading

    finish:
    push 0
    call exit
    end finish

end start

Solution

  • Update, question was changed from 64 bit blocks to 64 byte blocks, apparently by a third person (see comments after question, or look at edit history). Two examples below, one for 64 bit using fscanf / fprintf, one for 64 byte block using fread / fwrite.

    Which encryption scheme is to be used was not explained. This could affect the number of bytes per block, such as AES, which does 16 byte blocks (smaller blocks have to be padded to 16 bytes).

    Working example using Microsoft masm (ml.exe) for 64 bit copy.

            .data
    block64 dd      0,0                     ;two dd's for 64 bits
    pointer_source dd 0                     ;source FILE * value
    pointer_destination dd 0                ;dest   FILE * value
    
    msg_start   db "Source file path:",0
    source      db "                "       ;name of source file (read in)
    destination db "destination.txt",0      ;name of destination file
    fscanf_format db "%lld",0 
    fprintf_format db "%lld",10,0           ;added new line
    source_format db "%s", 0
    type_read db "r",0
    type_write db "w", 0
            .code
            ; ...
            push    offset msg_start
            call    printf
            add     esp,4
    
            ; read name source file
            push    offset source
            push    offset source_format
            call    scanf
            add     esp,8
    
            ; open source file
            push    offset type_read
            push    offset source
            call    fopen
            add     esp,8
            mov     pointer_source,eax      ;save source FILE *
    
            ; open destination file
            push    offset type_write
            push    offset destination
            call    fopen
            add     esp,8
            mov     pointer_destination,eax ;save destination FILE *
    
    reading:
            push    offset block64
            push    offset fscanf_format
            mov     eax,pointer_source      ;push file pointer value
            push    eax
            call    fscanf
            add     esp,12                  ;restore esp
            cmp     eax,0ffffffffh          ;br if end of file
            je      finish
            mov     eax,block64+4           ;push 64 bit block
            push    eax                     ;   
            mov     eax,block64             ;
            push    eax                     ;
            push    offset fprintf_format   ;push ptr to format string
            mov     eax,pointer_destination ;push file pointer value
            push    eax                     ;
            call    fprintf                 ;print value
            add     esp,16                  ;restore esp
            jmp     short reading           ;short is optional
    ;
    finish:
            mov     eax,pointer_destination ;push file pointer value
            push    eax                     ;
            call    fclose                  ;close file
            add     esp,4
            mov     eax,pointer_source      ;push file pointer value
            push    eax
            call    fclose                  ;close file
            add     esp,4
            push    dword ptr 0             ;(masm needs dword ptr)
            call    exit
    

    Example for 64 byte block copy.

            .data
    block64 db      64 dup (0)              ;64 byte buffer
    pointer_source dd 0                     ;source FILE * value
    pointer_destination dd 0                ;dest   FILE * value
    
    msg_start   db "Source file path:",0
    source      db "                "       ;name of source file (read in)
    destination db "destination.txt",0      ;name of destination file
    source_format db "%s", 0
    type_read db "rb",0                     ;read binary
    type_write db "wb", 0                   ;write binary
            .code
            ; ...
            push    offset msg_start
            call    printf
            add     esp,4
    
            ; read name source file
            push    offset source
            push    offset source_format
            call    scanf
            add     esp,8
    
            ; open source file
            push    offset type_read
            push    offset source
            call    fopen
            add     esp,8
            mov     pointer_source,eax      ;save source FILE *
    
            ; open destination file
            push    offset type_write
            push    offset destination
            call    fopen
            add     esp,8
            mov     pointer_destination,eax ;save destination FILE *
    
    reading:
            mov     eax,pointer_source      ;push FILE * value
            push    eax
            push    dword ptr 64            ;count
            push    dword ptr 1             ;size
            push    offset block64          ;ptr to buffer
            call    fread                   ;read 64 bytes (or less)
            add     esp,16                  ;restore esp
            test    eax,eax                 ;br if end file
            je      finish
            mov     ebx,pointer_destination ;push file pointer value (ebx)
            push    ebx                     ;
            push    eax                     ;count
            push    dword ptr 1             ;size
            push    offset block64          ;ptr to buffer
            call    fwrite                  ;write 64 bytes (or less)
            add     esp,16                  ;restore esp
            jmp     short reading           ;short is optional
    ;
    finish:
            mov     eax,pointer_destination ;push file pointer value
            push    eax                     ;
            call    fclose                  ;close file
            add     esp,4
            mov     eax,pointer_source      ;push file pointer value
            push    eax
            call    fclose                  ;close file
            add     esp,4
            push    dword ptr 0
            call    exit