flat assembler
Message board for the users of flat assembler.
Index
> Windows > Read the whole file and nothing else. |
Author |
|
revolution 11 Apr 2021, 18:45
For Windows there is not an easy solution AFAIAA. It doesn't give access to the low level driver. So no assembly code can help you. There is no API for that.
I suggest you boot up another OS (Linux maybe), or a dedicated program like Spinrite, and then read/recover/fix/whatever the HDD using the tools available. I am assuming you don't backups. If you do have backups then simply throw away the failing disk, buy a new one, and restore. |
|||
11 Apr 2021, 18:45 |
|
special-U 11 Apr 2021, 18:51
revolution wrote: I suggest you boot up another OS (Linux maybe), or a dedicated program like Spinrite, and then read/recover/fix/whatever the HDD using the tools available. Don't worry about the HDD, I'm not even trying to retrieve information, my question is just as it says above, just read and nothing else. I didn't say anything about recovering data. I will update the question for clarity. |
|||
11 Apr 2021, 18:51 |
|
revolution 11 Apr 2021, 20:13
You can read, but Windows will still hang because the driver will keep trying to read the dud sectors. Like I mentioned in the first paragraph, you get no API to tell Windows to give up sooner when reading bad sectors.
|
|||
11 Apr 2021, 20:13 |
|
Overclick 11 Apr 2021, 20:22
CHKDSK /f /r or something like that usually blocks dead sectors to avoid future usage.
|
|||
11 Apr 2021, 20:22 |
|
special-U 11 Apr 2021, 20:35
Overclick wrote: CHKDSK /f /r or something like that usually blocks dead sectors to avoid future usage. Thanks, I will make a note of it for the future. revolution wrote: You can read, but Windows will still hang because the driver will keep trying to read the dud sectors. Like I mentioned in the first paragraph, you get no API to tell Windows to give up sooner when reading bad sectors. Ok, no problem, let's let Windows freeze then, now can you help me read all the files in a folder? And no, it doesn't matter if Windows freezes or the information is lost, I just want to read with FASM. |
|||
11 Apr 2021, 20:35 |
|
FlierMate 11 Apr 2021, 20:38
I have an old code using INT 13 to read disk sector.
Just for your reference, to look at the old way of doing it. Code: function ReadSector(Drive,Head,Track,Sector,TotalSector:byte;DiskBuffer:pointer):byte; assembler; asm mov cx, RetryTime @retry: push cx mov ah, 02h mov al, TotalSector mov ch, Track mov cl, Sector mov dh, Head mov dl, Drive les bx, DiskBuffer int 13h pop cx jnc @finish loop @retry @finish: mov al, ah end; |
|||
11 Apr 2021, 20:38 |
|
revolution 11 Apr 2021, 20:43
I'm not sure what you are asking.
You can use the read API, just the same as the HLL will do. You won't get any extra magic from assembly here, Windows always has control. Windows eventually gives up, but it takes a while, and returns a failure condition to the caller. So upon each failure you can set some internal counter and do the read again from a new offset that skips the dud sector(s). If you do lots of smaller reads then you can build a map of which blocks read fine, and which fail. |
|||
11 Apr 2021, 20:43 |
|
special-U 11 Apr 2021, 20:56
revolution wrote: I'm not sure what you are asking. Sounds strange I know, but yes, I just want to read files recursively in a folder. revolution wrote: You can use the read API, just the same as the HLL will do. You won't get any extra magic from assembly here, Windows always has control. Do you mean this API? https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile Can you give me a code example of how to use that API? Windows APIs always seemed cryptic to me. |
|||
11 Apr 2021, 20:56 |
|
FlierMate 11 Apr 2021, 22:28
I am also learning modern Assembly like you.
This is my attempt to open a file to read the first 256 bytes. You may change the _filename to an existing file in your PC. Code: format PE console entry start include 'win32a.inc' section '.data' readable writable _message1 db 'INVALID_HANDLE_VALUE',13,10,0 _msglen1 = $ - _message1 _message2 db 'ReadFile FALSE',13,10,0 _msglen2 = $ - _message2 _dummy dw ? _filename db 'C:\FASM\MSGBOX.ASM',0 section '.code' code readable writable executable _buffer rb 256 _len dw ? start: invoke CreateFile, _filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 cmp eax, INVALID_HANDLE_VALUE je .error1 invoke ReadFile, eax, _buffer, 256, _len, 0 test eax, eax jz .error2 mov ecx, dword [_len] ;mov byte [_buffer+ecx], 0 jmp .show .error1: lea edx, [_message1] ; CreateFile ERROR mov ecx, _msglen1 jmp .error .error2: lea edx, [_message2] ; ReadFile ERROR mov ecx, _msglen2 .error: mov esi, edx lea edx, [_buffer] mov edi, edx mov dword [_len], ecx rep movsb .show: invoke GetStdHandle, -11 invoke WriteConsole, eax, _buffer, dword [_len], _dummy, 0 invoke ExitProcess,0 section '.idata' import readable writable library kernel32,'KERNEL32.DLL' import kernel32,\ GetStdHandle, 'GetStdHandle', \ ReadConsole, 'ReadConsoleA', \ WriteConsole, 'WriteConsoleA', \ CreateFile, 'CreateFileA', \ ReadFile, 'ReadFile', \ ExitProcess,'ExitProcess' |
|||
11 Apr 2021, 22:28 |
|
sleepsleep 11 Apr 2021, 23:55
maybe source of ddrescue,
https://www.gnu.org/software/ddrescue/ |
|||
11 Apr 2021, 23:55 |
|
bitRAKE 12 Apr 2021, 01:10
special-U wrote: help me read all the files in a folder? And no, it doesn't matter if Windows freezes or the information is lost, I just want to read with FASM. Has most the documentation for Windows that you need: https://docs.microsoft.com/en-us/windows/win32/fileio/file-management-functions You'd want to also read the file asynchronously (so your program can continue without waiting on a hung read command. Windows calls this "overlapped I/O". There are probably snippets on this board covering all those topics, but I'm not aware of a single source. Start with finding and reading a single file. The controller within the drive can hang, so it's not a Windows specific problem. Fine-grained control of the drive controller would be difficult under windows. There are commands to reset the drive, etc. that specialized software would use. _________________ ¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup |
|||
12 Apr 2021, 01:10 |
|
revolution 12 Apr 2021, 06:25
bitRAKE wrote: The controller within the drive can hang, so it's not a Windows specific problem. That is why I suggested above to use other tools, not Windows. Then you can get the job much more easily and quicker without all the boring waiting around to read sectors that can't be read. |
|||
12 Apr 2021, 06:25 |
|
special-U 12 Apr 2021, 07:10
FlierMate wrote: This is my attempt to open a file to read the first 256 bytes. Can I put C code here? or is it not allowed? while waiting for your answer, I will leave a code that reads the whole file but it is even slower than my Ruby version, what am I doing wrong? Also the buffer is very small but C won't let me make it bigger. Code: #include <Windows.h> int main(void){ HANDLE fh = CreateFile("D:\\A_File_Of_5GB.zip", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); DWORD bytesRead; bytesRead = 4294967295; char readBuffer[1048576]; while (ReadFile(fh, readBuffer, sizeof(readBuffer), &bytesRead, NULL)){ if (bytesRead == 0) break; } |
|||
12 Apr 2021, 07:10 |
|
FlierMate 12 Apr 2021, 11:16
special-U wrote:
Done! Code: format PE console entry start include 'win32a.inc' section '.data' readable writable _message1 db 'INVALID_HANDLE_VALUE',13,10,0 _msglen1 = $ - _message1 _message2 db 'ReadFile FALSE',13,10,0 _msglen2 = $ - _message2 _dummy dw ? _filename db 'C:\FASM\LARGE.txt',0 _format db '%d',0 section '.code' code readable writable executable _buffer rb 1024 _len dd ? _ptr dd ? _handle dd ? start: invoke CreateFile, _filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 mov dword [_handle], eax cmp eax, INVALID_HANDLE_VALUE je .error1 .repeat: invoke ReadFile, dword [_handle], _buffer, 1024, _len, 0 test eax, eax jz .error2 mov ecx, dword [_len] add dword [_ptr], ecx test ecx, ecx jz .done invoke GetStdHandle, -11 invoke WriteFile, eax, _buffer, dword [_len], _dummy, 0 invoke SetFilePointer, dword [_handle], dword [_ptr], 0, FILE_BEGIN cmp eax, -1 ;INVALID_SET_FILE_POINTER je .error3 jmp .repeat .error1: lea edx, [_message1] mov ecx, _msglen1 jmp .error .error2: lea edx, [_message2] mov ecx, _msglen2 jmp .error .error3: invoke GetLastError ;cmp eax, 997 ; ERROR_IO_PENDING ;je .repeat push eax push _format push _buffer call [wsprintf] mov dword [_len], 5 jmp .show .error: mov esi, edx lea edx, [_buffer] mov edi, edx mov dword [_len], ecx rep movsb .show: invoke GetStdHandle, -11 invoke WriteConsole, eax, _buffer, dword [_len], _dummy, 0 .done: invoke ExitProcess,0 section '.idata' import readable writable library kernel32, 'KERNEL32.DLL', \ user32, 'USER32.DLL' import kernel32,\ GetStdHandle, 'GetStdHandle', \ ReadConsole, 'ReadConsoleA', \ WriteConsole, 'WriteConsoleA', \ CreateFile, 'CreateFileA', \ ReadFile, 'ReadFile', \ WriteFile, 'WriteFile', \ GetLastError, 'GetLastError', \ SetFilePointer, 'SetFilePointer', \ SetFilePointerEx, 'SetFilePointerEx', \ ExitProcess,'ExitProcess' import user32,\ wsprintf, 'wsprintfA' You can redirect the output of this program, and then compare the size of output file with original file. E.g. FASMW --> Save as "READFILE.ASM" -- > Compile Type "READFILE > DUMP.TXT" --> "FC /B LARGE.TXT DUMP.TXT" (only work for text files) But my example only work for 32-bit addressing of input file size only (max 4GB?), you can refer to SetFilePointer and SetFilePointerEx for 64-bit addressing and beyond. Hope this helps. |
|||
12 Apr 2021, 11:16 |
|
Overclick 12 Apr 2021, 11:36
What about direct work with sectors?
https://www.codeproject.com/Articles/28314/Reading-and-Writing-to-Raw-Disk-Sectors |
|||
12 Apr 2021, 11:36 |
|
FlierMate 17 Apr 2021, 19:19
Below is a better version which accepts input file name from command line.
Usage: DUMPFILE large.txt DUMPFILE large.txt > dump.txt Code: ; Open File and Read File (Extended Version with Command Line File Name Support) ; ; DUMPFILE.ASM ; Copyright (C) 2021 Boo Khan Ming ; ; MIT license apply ; format PE console entry start include 'win32a.inc' section '.data' readable writable _message1 db 'INVALID_HANDLE_VALUE',13,10,0 _msglen1 = $ - _message1 _message2 db 'ReadFile FALSE',13,10,0 _msglen2 = $ - _message2 _dummy dw ? ;_filename db 'LARGE.BIN',0 _format db '%d',0 section '.code' code readable writable executable _filename rb MAX_PATH _fnlen dd ? _buffer rb 1024 _len dd ? _ptr dd ? _handle dd ? start: invoke GetCommandLine push eax mov edi, eax or ecx, -1 xor eax, eax repnz scasb ; Calculate total length of command line arguments not ecx pop eax mov dword [_fnlen], ecx push eax mov edi, eax or ecx, -1 mov eax, 32 repnz scasb ; Calculate length of first command line argument (APPNAME) not ecx pop eax inc ecx sub dword [_fnlen], ecx ; Compute the length of second command line argument (_FILENAME) add eax, ecx mov ecx, dword [_fnlen] mov esi, eax lea edx, [_filename] mov edi, edx rep movsb ;invoke GetStdHandle, -11 ;invoke WriteConsole, eax, _filename, dword [_fnlen], _dummy, 0 invoke CreateFile, _filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 mov dword [_handle], eax cmp eax, INVALID_HANDLE_VALUE je .error1 .repeat: invoke ReadFile, dword [_handle], _buffer, 1024, _len, 0 test eax, eax jz .error2 mov ecx, dword [_len] add dword [_ptr], ecx test ecx, ecx jz .done invoke GetStdHandle, -11 invoke WriteFile, eax, _buffer, dword [_len], _dummy, 0 invoke SetFilePointer, dword [_handle], dword [_ptr], 0, FILE_BEGIN cmp eax, -1 ;INVALID_SET_FILE_POINTER je .error3 jmp .repeat .error1: lea edx, [_message1] mov ecx, _msglen1 jmp .error .error2: lea edx, [_message2] mov ecx, _msglen2 jmp .error .error3: invoke GetLastError ;cmp eax, 997 ; ERROR_IO_PENDING ;je .repeat push eax push _format push _buffer call [wsprintf] mov dword [_len], 5 jmp .show .error: mov esi, edx lea edx, [_buffer] mov edi, edx mov dword [_len], ecx rep movsb .show: invoke GetStdHandle, -11 invoke WriteConsole, eax, _buffer, dword [_len], _dummy, 0 .done: invoke ExitProcess,0 section '.idata' import readable writable library kernel32, 'KERNEL32.DLL', \ user32, 'USER32.DLL' import kernel32,\ GetStdHandle, 'GetStdHandle', \ ReadConsole, 'ReadConsoleA', \ WriteConsole, 'WriteConsoleA', \ CreateFile, 'CreateFileA', \ ReadFile, 'ReadFile', \ WriteFile, 'WriteFile', \ GetLastError, 'GetLastError', \ SetFilePointer, 'SetFilePointer', \ SetFilePointerEx, 'SetFilePointerEx', \ GetCommandLine, 'GetCommandLineA', \ ExitProcess,'ExitProcess' import user32,\ wsprintf, 'wsprintfA' This program is slower than CMD copy command. Code: 4MB 2GB DUMPFILE.ASM 281 ms 1 min 42 sec 985 ms COPY 187 ms 33 sec 687 ms BTW, the upper limit of file size supported by Assembly code above is 2GB (2^32 / 2) |
|||
17 Apr 2021, 19:19 |
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.