I'm learning assembly, but I've been learning on Linux, and it's been very interwoven with C/C since I understand C/C .
However, now, I want to write a program in assembly on my Windows computer that makes a call to a function that runs a shell command, and hopefully without including any libraries since I want this executable to be as small as possible. (A simple C executable I made which included cstdlib
is 32 KB while I typed barely any code at all.)
I want to essentially write this program but in assembly:
#include <cstdlib>
int main()
{
system("echo ABCDEFG> msg.txt");
system("type msg.txt");
return 0;
}
So far, I have installed NASM and MinGW and I'm trying to use them [Edit: I am now trying to use MASM instead, with Visual Studio], but nothing works and I assume it's because Windows has its own stuff from Microsoft that obviously aren't in Linux, but none of the online resources I've come across have successfully compiled with what I was trying to do. It also doesn't seem to understand the statement extern system
, so I think that this might be a C/C library thing (from cstdlib
).
Also, in some cases I encountered an error where it said the "character constant is too long". I assume it's referring to the string; in the real program, the string to echo is much longer than what's in the example above.
I also had an issue apparently with the .obj file that was generated.
So, basically, all I need is how to turn the above program into assembly for Windows, and how to get NASM and MinGW to turn it into an executable without giving me errors.
Edit: After a few days of researching, I have decided I don't know what I'm doing wrong and I can't figure out what is right.
I've tried Visual Studio now, but once again, it doesn't understand extern system
.
.386
.model flat, stdcall
.stack 4096
ExitProcess PROTO, dwExitCode: DWORD
.data
Var db 'dir && pause', 0
.code
extern system
main PROC
push ebp
mov ebp, esp
sub esp, 32
lea ecx, [Var]
call system
xor eax, eax
INVOKE ExitProcess, 0
main ENDP
END main
CodePudding user response:
As I mentioned in the comments, Windows does have a system command. It's located in MSVCRT.dll, so you'll need to link with msvcrt.lib to resolve the external reference.
The error you are getting from "line 11" is due to incorrectly defining the external, which is odd since you're correctly doing the same for ExitProcess (which is also an external) just a few lines before.
32k may sound big, but Windows works in 4k pages these days, allowing it set page protection bits (read-only pages, executable pages, etc). One page for executable code, one for data, one for constants, imports, exports, debug info, exception info, etc. 8 pages doesn't seem that outrageous by today's standards.
But as I also mentioned, there are hacks one can use to reduce the size of the executable if there's some compelling reason to do so. This sample (built with NASM version 2.15.05 using nasm.exe doit.asm -o doit.exe
) is 1,184 bytes. When you run it, nothing seems to happen (no cmd window opens) and it's really quick. But you'll see that foo.xxx gets created and contains the output from the dir > foo.xxx
command embedded in the code.
There's a lot of gobbledygook here that the linker normally handles for you. The interesting bits start at ENTRY:
. cmd is defined near the end of the code.
The stealthy nature of this code combined with the small size opens the possibility of using this code for mischief. I'm going to assume that's not your intent.
; Check for NASM version at least 2.15.05
%if __?NASM_VERSION_ID?__ < 0x0020F0500
%error "Newer version of nasm required"
%endif