i'm having a bit of trouble with assembly, I'm using TASM for compiling and TLINK for linking (yes I know these are old and outdated, but switching isn't currently an option so please don't suggest that).
Here is the situation. A user types in a path in console, program jumps to that directory and tries to open any files inside. I only know how to access files when I know their name. So how would one do something like this?
P.S. though general logic is fine too, if you write any code please comment it, I'm very much new to this.
You have to scan the directory. Depending upon your SO, this is done by different ways. For example, if you are in DOS environment, which is what I assume by the tools you are using, this is accomplished by using function 4Eh of int 21h. Then, you can use service 4Fh to get subsequents files.
DS:DX must point to the ASCIIZ string containing the path where you want to search for files. The path must include the file name, or some kind of wilcard (for example *.* if you want to scan the complete directory). This is for function 4Eh. Function 4Fh resumes the scan from the file following the one that was found by function 4Eh or a previous call to function 4Fh.
A code for this would be:
;setup a DTA for scanning directories
mov dx,offset of your DTA block
mov ax,segment of your DTA block (normally your current data segment)
mov ds,ax
mov ah,1Ah
int 21h
;setup registers for int 21h,4Eh
;including DS:DX = ASCIIZ string with path and possibly, wilcard.
;......
;......
mov ah,4Eh
int 21h
cmp cx,0
jnz NoMoreFiles
NextFile:
;Parse DTA to obtain filename and extension of the first file found (at offset 30d)
;......
;......
mov ah,4Fh
int 21h
jc NoMoreFiles
jmp NextFile
NoMoreFiles:
More details about what DOS services to use and what parameters they expect, here:
http://bbc.nvg.org/doc/Master%20512%20Technical%20Guide/m512techb_int21.htm
Related
For this C source code:
int add(int a, int b) { return a + b; }
, the Watcom C Compiler for 8086 (wcc -s -ms -os -0 prog.c) generates the following machine code (hex): 01 D0 C3, disassembling to add ax, dx (01 D0) + ret (C3).
For this assembly source code:
PUBLIC add_
EXTRN _small_code_:BYTE
_TEXT SEGMENT BYTE PUBLIC USE16 'CODE'
add_: add ax, dx
ret
_TEXT ENDS
END
, the Watcom Assembler (WASM, wasm -ms -0 prog.wasm) generates the following machine code (hex): 03 C2 C3, disassembling to add ax, dx (03 C2) + ret (C3).
Thus they generate a different binary encoding of the same 8086 assembly instruction add ax, dx.
FYI If I implement the the function in Watcom C inline assembly, then the machine code output will be the same as with WASM.
A collection of different instruction encodings:
add ax, dx. wcc: 01 D0; wasm: 03 C2.
mov bx, ax. wcc: 89 C3; wasm: 8B D8.
add ax, byte 9. wcc: 05 09 00; wasm: 83 C0 09.
How can I make the Watcom C compiler (for C code) and WASM generate the instructions with the same binary encoding? Is there a command-line flag or some other configuration option for either? I wasn't able to find any.
The reason why I need it is that I'd like to reproduce an executable program file written in Watcom C by writing WASM source only, and I want the final output be bit-by-bit identical to the original.
This answer is inspired by a comment by #RaymondChen.
Here is a cumbersome, multistep way to change the machine code emitted by wcc to match the output of wasm:
Compile the C source code witm wcc (part of OpenWatcom) to .obj file as usual.
Use dmpobj (part of OpenWatcom) to extract the machine code bytes of the _TEXT segment.
Use ndisasm (part of NASM, ndisasm -b 16 file.obj) to disassemble the machine code bytes.
Write and run custom source text filter to keep the assembly instructions only and convert them WASM syntax.
Use wasm (part of OpenWatcom) to generate the 2nd .obj file.
Use dmpobj to extract the machine code bytes of the _TEXT segment of the 2nd .obj file.
Write and run a custom binary filter to replace the machine code bytes in the _TEXT segment of the 1st .obj file from the equivalent bytes extracted from the 2nd .obj file, using the offsets in the outputs of the dmpobj invocations.
These steps avoid using wdis -a (conversion from .obj to assembly source), because that's lossy (it doesn't include everything in the .obj file), which can potentially make unwanted changes, causing problems later.
Currently using Microsoft Visual Studio Community 2019 Version 16.4.4 and compiling a C project.
I want to be able to output assembly from VS, make modifications to the assembly, and then compile the modified assembly into an executable file. Below I talk about my attempts following instructions from a previous SO question, but if there is an alternative (even not using VS) I would appreciate those suggestions.
As a test, I have been using a simple "hello world" program:
#include <stdio.h>
int main(int argc, char* argv) {
printf("Hello world\n");
return 0;
}
I have tried compiling this program following the instructions given by this answer but I get the following errors:
LNK2005 ___local_stdio_printf_options already defined in helloworld.obj
LNK1169 one or more multiply defined symbols found
It looks like VS is actually compiling the assembly to object files, but the linker says that the "___local_stdio_printf_options" symbol is already defined at link-time. When I look back at the assembly code output from VS, this seems to be true:
___local_stdio_printf_options PROC ; COMDAT
; File C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\corecrt_stdio_config.h
; Line 86
push ebp
mov ebp, esp
; Line 88
mov eax, OFFSET ?_OptionsStorage#?1??__local_stdio_printf_options##9#9 ; `__local_stdio_printf_options'::`2'::_OptionsStorage
; Line 89
pop ebp
ret 0
___local_stdio_printf_options ENDP
So it looks like the a solution for this may be to prevent the VS compiler from defining ___local_stdio_printf_options or change the linker setting to accept this style of coding somehow. I don't know why VS would produce code that defines external symbols like this. I would really appreciate any help.
In C I'm using 'open()' to create and open files:
fd = open(fileName, O_CREAT | O_RDWR, 0644);
if 'fileName' includes a directory the file is created only if the directory exists and the application has permission to write to this directory.
If the directory does not exists 'open()' returns an error and I would like to create the directory.
With makedir (see below) I am able to create the directory.
int mkdir(const char *path, mode_t mode);
I was wondering, are there other ways to create a directory? I believe we can also use ioctl()? Are there more alternatives?
I'm asking this because in our code we are not allowed to use mkdir.
I was wondering, are there other ways to create a directory? I believe we can also use ioctl()?
At least on Linux and HP-UX, mkdir is a system call on its own.
So, No, there is no other way to create a directory, at least not on Linux - other systems might implement directory creation differently. But on any reasonable system, I would expect directory creation to be a privileged operation, so you need to go through the kernel.
The only slightly different approach would be to execute the system call directly, by bypassing the C runtime library. In assembly nasm syntax on an i386 architecture, this would look something like
mkdir:
mov eax, 39 ; System-call "sys_mkdir"
mov ebx, dirName ; directory name to create
mov ecx, 0x755 ; creation mode
int 80H ; call sys_mkdir
However, this is not something you would normally do since it is completely system dependant. Switching to a different CPU would require different register setup and/or different instructions - that is what the C runtime library encapsulates.
See also
http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html
http://asm.sourceforge.net/syscall.html
http://en.wikipedia.org/wiki/System_call
A kernel driver can create a folder using
struct file *fp = (struct file *) NULL;
fp = filp_open("/home/testdir", O_DIRECTORY|O_CREAT, S_IRUSR);
I can imagine some situations when a "make_dir" driver which creates large number of folders will be faster than calling mkdir for every folder.
I'm currently trying to write to a file so far I have the following code to append to the file. Does anybody know why this isn't working? It runs fine but by the end nothing has changed.
filewritemode: .asciz "a"
filelocation: .asciz "/h/test.txt"
_main:
push $filelocation
push $filewritemode
call _fopen
push $blabla
push %eax
call _fprintf
push $result
call _printf
push $0
call _exit # exit the program
gcc is used in order to turn the source file into an .exe
$blabla is currently the string with some random chars that are ment for testing
It doesn't work because you have pushed the parameters of fopen in the wrong order. Parameters must be pushed from last to first. Aside from that you are repeatedly pushing parameters, but you don't remove them again. In this case that works because you take a dive to exit, but if instead you would have returned with the ret instruction, you would have found that this would result in a crash as you would be jumping to one of the pushed parameters.
You are passing the arguments to fopen reversed and you are not checking for errors. In situations like this, ltrace may be your friend.
Just started to step my kernel mode usb driver and it is in assembler. How do I configure WinDbg to c-level debugging? This is how i looks now =/
MyDriver!MyDriver_EvtDeviceAdd+0xb:
af20801b 833d647020af03 cmp dword ptr [MyDriver!DebugLevel (af207064)],3
0: kd> p
MyDriver!MyDriver_EvtDeviceAdd+0x2e:
af20803e ff15006020af call dword ptr [MyDriver!_imp__KeGetCurrentIrql (af206000)]
0: kd> p
MyDriver!MyDriver_EvtDeviceAdd+0x58:
af208068 8d95a8feffff lea edx,[ebp-158h]
0: kd> p
MyDriver!MyDriver_EvtDeviceAdd+0x64:
af208074 c785bcfeffff508420af mov dword ptr [ebp-144h],offset MyDriver!MyDriver_EvtDevicePrepareHardware (af208450)
WinDbg cannot find pdb files. Fill properly all WinDbg paths:
Symbol search path - must include driver .pdb files and local path for MS debugging symbols.
Source search path - must include directory with driver source files.
Image file path - must contain driver .sys file.
Look at WinDbg log: it reports all errors trying to load debug information. If you see something like "Cannot load debug information for your_driver.sys", something is wrong.
Your symbols look fine based on the output above. If you're not getting your source window popping up, you're typically in one of two cases:
1) You've moved your source code from where you originally built it. By default, the PDBs have the fully qualified path to the orignal source code location. If you move it, WinDBG won't be able to find it. You can see where WinDBG is looking by doing:
u MyDriver!MyDriver_EvtDeviceAdd
That should give you the full path of the source module containing that function embedded in the PDB. You can override this path by setting your Source Search Path to point to the new location.
2) You've managed to hide the source window somehow. Seems silly, but happens to my students all the time :) Check under the "Window" menu item in WinDBG to see if the window is open somewhere.
To clarify an earlier point, you do not need to set your Image File Path in this case. The only time that is required is if you're debugging a mini-dump.
-scott
You need to ensure you are generating "Codeview"/debug symbols for your driver, and the file generated is accessible to Windbg.