flat assembler
Message board for the users of flat assembler.

Index > Windows > How do I read a file byte by byte?

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
dgfydx



Joined: 26 May 2020
Posts: 2
Location: USA
dgfydx
I'm trying to make a simple stack based virtual machine/bytecode interpreter in fasm similar to this, but with a few more features. One feature I want to add is the ability to read from files. I want to read each byte from a file, and do different things based on what the byte is.
I tried to this, but it isn't working. Every time I try to run my program with a file, it prints out a random string of string of characters. Here is my code:
Code:
format PE64 console 6.0
include 'win64a.inc'

section '.code' code readable executable
entry $
        invoke __getmainargs, argc, argv, env, 0
        cmp [argc], 2
        jne argError
        mov rsi, [argv]
        invoke GetFileAttributes, qword [rsi + 8]
        cmp eax, -1
        je fileError
        mov rax, qword [rsi + 8]
        invoke fopen, rax, "rb"
read:
        invoke fgetc, rax
        invoke printf, [fgetc]
        jmp read
exit:
        invoke fclose, rax
    invoke ExitProcess, 0
argError:
        invoke printf, printArgError
        jmp exit
fileError:
        invoke printf, printFileError
        jmp exit


section '.bss' data readable writable
argc dq ?
argv dq ?
env dq ?

section '.rdata' data readable
printArgError db 'Error: Wrong number of arguments. Run file with "program.exe <file>"', 0
printFileError db 'Error: File does not exist. Check spelling and try again.', 0


section '.idata' data readable import
library kernel32, 'kernel32.dll', msvcrt, 'msvcrt.dll'
import kernel32, ExitProcess,'ExitProcess', GetFileAttributes, 'GetFileAttributesA'
import msvcrt, printf, 'printf', __getmainargs, '__getmainargs', fopen,'fopen', fclose, 'fclose', fread, 'fread', fgetc, 'fgetc'
    


I always get this output:
Quote:
Hë\$HëLWHâ∞0Hï┘3 Hà╔u-Φ┬»√ ╟


What am I doing wrong? Can somebody help me?
Post 26 May 2020, 21:38
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3045
Location: vpcmipstrm
bitRAKE
The first thing I do is fire up the debugger. It goes like, F8, F8, F8, ... I'm looking at the stack address and bam! 8 MOD 16 - some of the API code executes just fine, but at least one requires the alignment the ABI asks for.

Why is it out of alignment?
Because you used "win64a/entry $" - which means you are responsible.

If you want to let fasm handled the hairy details use "win64ax/.code/Start:/.end Start"

Or do what I do, just pop the return address - you don't need it.

_________________
¯\(°_o)/¯ unlicense.org
Post 26 May 2020, 21:53
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3045
Location: vpcmipstrm
bitRAKE
That doesn't appear to be it. and __getmainargs doesn't like POP RAX, lol. It's reading way up the stack for some reason. It's definitely expecting more arguments. Hm... documentation says it needs a pointer to another parameter...
Code:
int __getmainargs(
    int * _Argc,
   char *** _Argv,
   char *** _Env,
   int _DoWildCard,
_startupinfo * _StartInfo);    
"Other information to be passed to the CRT DLL."

Oh, the culprit is "invoke printf, [fgetc]" passing the pointer of the fgetc function into printf. Very Happy
Post 26 May 2020, 22:07
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3045
Location: vpcmipstrm
bitRAKE
Code:
format PE64 console 6.0
include 'win64a.inc'

section '.code' code readable executable
entry $
pop rax ; align stack

        invoke __getmainargs, argc, argv, env, 0, stup
        cmp [argc], 2
        jne argError
        mov rsi, [argv]
        invoke GetFileAttributes, qword [rsi + 8]
        cmp eax, -1
        je fileError
        mov rax, qword [rsi + 8]
        invoke fopen, rax, "rb"
        mov [stream], rax
read:
        invoke fgetc, [stream]
        lea ecx,[eax+1]
        jrcxz exit ; EOF detection
        mov [one_char],rax
        invoke printf, one_char
        jmp read
exit:
        invoke fclose, [stream]
    invoke ExitProcess, 0
argError:
        invoke printf, printArgError
        jmp exit
fileError:
        invoke printf, printFileError
        jmp exit


section '.bss' data readable writable
argc dq ?
argv dq ?
env dq ?
stup dq ?

stream dq ?
one_char dq ?

section '.rdata' data readable
printArgError db 'Error: Wrong number of arguments. Run file with "program.exe <file>"', 0
printFileError db 'Error: File does not exist. Check spelling and try again.', 0


section '.idata' data readable import
library kernel32, 'kernel32.dll', msvcrt, 'msvcrt.dll'
import kernel32, ExitProcess,'ExitProcess', GetFileAttributes, 'GetFileAttributesA'
import msvcrt, printf, 'printf', __getmainargs, '__getmainargs', fopen,'fopen', fclose, 'fclose', fread, 'fread', fgetc, 'fgetc'    
Fixed many problems, please look at API documentation. Need to save the stream handle. Need to pass a pointer to a string to printf, etc.

Get comfortable with x64dbg.com it'll save you a lot of time.
Post 26 May 2020, 22:28
View user's profile Send private message Visit poster's website Reply with quote
dgfydx



Joined: 26 May 2020
Posts: 2
Location: USA
dgfydx
Wow, thank you so much! I'm still a beginner to assembly, so this was very useful to learn from. Thanks for the recommendation of x64dbg, it seems very helpful. I do have one question about your code. What's the purpose of the jrcxz instruction? Is it different from using test rcx, rcx?
Post 27 May 2020, 00:32
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17669
Location: In your JS exploiting you and your system
revolution
jrcxz => jump if rcx=0
Post 27 May 2020, 03:44
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 815
Roman
Jrcxnz exist? Jump if rcx not 0
Post 27 May 2020, 06:28
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17669
Location: In your JS exploiting you and your system
revolution
Roman wrote:
Jrcxnz exist? Jump if rcx not 0
No.
Post 27 May 2020, 06:52
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 815
Roman
Intel fail Smile
Post 27 May 2020, 06:58
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 821
Location: Belarus
DimonSoft
I’m always surprised seeing asm-program using C library. Why? If you want to use C library, write in C. Why fill your program with crappy dated back to 1970 design mistakes?

You won’t even get cross-platformness this way, so what’s the reason to use fopen and have another dependency in your program (for which Windows is NOT a delivery channel) when we already have CreateFile in kernel32.dll that is already there, and CreateFileMapping for really efficient byte-by-byte file handling, and all that’s for free?
Post 27 May 2020, 07:37
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 579
Location: Russian Federation, Sochi
ProMiNick
DimonSoft, I absolutely agree msvcrt is ugly & useless.
But maybe dgfydx dosn`t know winapis, only C slow wrappers over them.
Or maybe his final target of learning assembly - inline asm in HLL (and using of msvcrt would be there anyway).

Anyway using by newbies such thing as msvcrt are available because someone (not very) smart (but enough skilled) implements this headers/that only his guilty, not newbies.
Post 27 May 2020, 09:59
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17669
Location: In your JS exploiting you and your system
revolution
revolution wrote:
Roman wrote:
Jrcxnz exist? Jump if rcx not 0
No.
Roman wrote:
Intel fail Smile
Code:
macro jrcxnz target {
  local ..skip
  jrcxz ..skip
  jmp target
 ..skip:
}    
Solved.
Post 27 May 2020, 10:19
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3045
Location: vpcmipstrm
bitRAKE
revolution wrote:
Roman wrote:
Jrcxnz exist? Jump if rcx not 0
No.
Code:
macro JRCXNZ? target*
        inc rcx
        loop target
end macro    
Cool
https://github.com/bitRAKE/fasmg_playground/blob/master/math/branching.txt

_________________
¯\(°_o)/¯ unlicense.org
Post 27 May 2020, 10:31
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17669
Location: In your JS exploiting you and your system
revolution
bitRAKE wrote:
Code:
macro JRCXNZ? target*
        inc rcx
        loop target
end macro    
Cool
https://github.com/bitRAKE/fasmg_playground/blob/master/math/branching.txt
Your code changes EFLAGS Confused
Post 27 May 2020, 10:46
View user's profile Send private message Visit poster's website Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 815
Roman
loop slow.

implement JRCXNZ
Code:
test rcx,rcx
jnz label
    
Post 27 May 2020, 11:27
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
revolution wrote:
bitRAKE wrote:
Code:
macro JRCXNZ? target*
        inc rcx
        loop target
end macro    
Cool
https://github.com/bitRAKE/fasmg_playground/blob/master/math/branching.txt
Your code changes EFLAGS Confused
Code:
macro jecxz target
{
        if target-($+1) < 80h & target-($+1) >= -80h
                jecxz   target
        else
                local   j,k
                jecxz   j
                jmp     k
            j:  jmp     target
            k:
        end if
}

macro jnecxz target
{
        local   k
        jecxz   k
        jmp     target
    k:
}    
Based on full-range JECXZ emulation that I needed to assemble fasmg with USE64.
Roman wrote:
loop slow.

implement JRCXNZ
Code:
test rcx,rcx
jnz label
    
This one changes even more flags!
Post 27 May 2020, 11:30
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 17669
Location: In your JS exploiting you and your system
revolution
Tomasz Grysztar wrote:
Code:
macro jecxz target
{
        if target-($+1) < 80h & target-($+1) >= -80h
                jecxz   target
        else
                local   j,k
                jecxz   j
                jmp     k
            j:  jmp     target
            k:
        end if
}

macro jnecxz target
{
        local   k
        jecxz   k
        jmp     target
    k:
}    
Your code changes the base label. Confused
Post 27 May 2020, 11:43
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3045
Location: vpcmipstrm
bitRAKE
The nice thing about Assembly is that we often control the number ranges - it wouldn't be unusual to be able to eliminate the INC instruction. Also, it works for any value we want to branch out of the loop for:
Code:
macro JREGN_VAL? target,reg,value
        lea rcx,[reg-value+1]
        loop target
end macro    
Ultimately, it's just a tool in the toolbox to get the mind working.

_________________
¯\(°_o)/¯ unlicense.org
Post 27 May 2020, 11:44
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 7797
Location: Kraków, Poland
Tomasz Grysztar
revolution wrote:
Your code changes the base label. Confused
Not in fasmg, where this macro has been originally made. I then adapted it back to fasm 1 with as little changes as possible as I did not care about other uses anyway (I do not use dot-locals in fasmg sources).
Post 27 May 2020, 11:47
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 3045
Location: vpcmipstrm
bitRAKE
LOOP is slow, but what about the others LOOPZ LOOPNZ? We can do two decisions in a single instruction. Which makes it smaller and faster when the need arises. If you don't know it exists - it becomes much harder to see.

BTW, Ryzen has made LOOP the same speed as Jcc (fused CMP/Jcc is still faster). Forget LOOPx on Skylake - Intel is so compiler orientated.
Post 27 May 2020, 11:59
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< 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 GitHub, YouTube, Twitter.

Website powered by rwasa.