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 |
|
dgfydx 26 May 2020, 21:38
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? |
|||
26 May 2020, 21:38 |
|
bitRAKE 26 May 2020, 22:07
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); Oh, the culprit is "invoke printf, [fgetc]" passing the pointer of the fgetc function into printf. |
|||
26 May 2020, 22:07 |
|
bitRAKE 26 May 2020, 22:28
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' Get comfortable with x64dbg.com it'll save you a lot of time. |
|||
26 May 2020, 22:28 |
|
dgfydx 27 May 2020, 00:32
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?
|
|||
27 May 2020, 00:32 |
|
revolution 27 May 2020, 03:44
jrcxz => jump if rcx=0
|
|||
27 May 2020, 03:44 |
|
Roman 27 May 2020, 06:28
Jrcxnz exist? Jump if rcx not 0
|
|||
27 May 2020, 06:28 |
|
revolution 27 May 2020, 06:52
Roman wrote: Jrcxnz exist? Jump if rcx not 0 |
|||
27 May 2020, 06:52 |
|
Roman 27 May 2020, 06:58
Intel fail
|
|||
27 May 2020, 06:58 |
|
DimonSoft 27 May 2020, 07:37
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? |
|||
27 May 2020, 07:37 |
|
ProMiNick 27 May 2020, 09:59
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. |
|||
27 May 2020, 09:59 |
|
revolution 27 May 2020, 10:19
revolution wrote:
Roman wrote: Intel fail Code: macro jrcxnz target { local ..skip jrcxz ..skip jmp target ..skip: } |
|||
27 May 2020, 10:19 |
|
bitRAKE 27 May 2020, 10:31
revolution wrote:
Code: macro JRCXNZ? target*
inc rcx
loop target
end macro https://github.com/bitRAKE/fasmg_playground/blob/master/math/branching.txt _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
27 May 2020, 10:31 |
|
revolution 27 May 2020, 10:46
bitRAKE wrote:
|
|||
27 May 2020, 10:46 |
|
Roman 27 May 2020, 11:27
loop slow.
implement JRCXNZ Code:
test rcx,rcx
jnz label
|
|||
27 May 2020, 11:27 |
|
Tomasz Grysztar 27 May 2020, 11:30
revolution 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: } Roman wrote: loop slow. |
|||
27 May 2020, 11:30 |
|
revolution 27 May 2020, 11:43
Tomasz Grysztar wrote:
|
|||
27 May 2020, 11:43 |
|
bitRAKE 27 May 2020, 11:44
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 _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
27 May 2020, 11:44 |
|
Tomasz Grysztar 27 May 2020, 11:47
revolution wrote: Your code changes the base label. |
|||
27 May 2020, 11:47 |
|
bitRAKE 27 May 2020, 11:59
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. |
|||
27 May 2020, 11:59 |
|
Goto page 1, 2 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.